将SSE2迁移到Arm NEON内在函数

时间:2011-09-26 12:42:01

标签: kinect neon sse2

我在SSE2 intrinsincs中有以下代码。它处理来自Kinect的输入。

__m128i md = _mm_setr_epi16((r0<<3)  | (r1>>5), ((r1<<6)  | (r2>>2) ), ((r2<<9)  | (r3<<1) | (r4>>7) ), ((r4<<4)  | (r5>>4) ), ((r5<<7)  | (r6>>1) ),((r6<<10) | (r7<<2) | (r8>>6) ), ((r8<<5)  | (r9>>3) ), ((r9<<8)  | (r10)   ));
md = _mm_and_si128(md, mmask);
__m128i mz = _mm_load_si128((__m128i *) &depth_ref_z[i]);
__m128i mZ = _mm_load_si128((__m128i *) &depth_ref_Z[i]);
mz = _mm_cmpgt_epi16(md, mz);
mZ = _mm_cmpgt_epi16(mZ, md);
mz = _mm_and_si128(mz, mZ);
md = _mm_and_si128(mz, md);
_mm_store_si128((__m128i *) frame,md)
if(_mm_movemask_epi8(mz)){ ... }

这基本上在SSE寄存器中将11 uint8_t(r0-r10​​)解包为8 uint16_t(mmask是常量并且先前已创建)。然后它再加载两个寄存器,其中两个数组中的相应元素用作边界。它会检查它们并创建一个寄存器,其中包含的元素不符合标准清零。然后它存储它们并进一步处理每个元素。当没有元素通过时,movemask作为一个很好的优化,在这种情况下可以跳过处理。

这很好用,现在我想将它移植到NEON。除了两个部分,大部分内容都很简单。查看SSE2代码中的汇编输出(gcc),我发现在_mm_setr_epi16中没有进行8次uint16_t移动,而是将它们移动到uint32_t,最后进行4次移动。这似乎很有效,因为编译器会处理它,我没有更改代码。我应该在NEON案例中手动申请吗?而不是8 vsetq_lane_u16进行转换并执行4 vsetq_lane_u32?我对endianess有任何问题并且值得吗?

最后一部分是movemask,因为我找不到相应的东西。有谁能提出建议?

1 个答案:

答案 0 :(得分:1)

我更喜欢从普通C代码而不是SSE2开始;在这个低级别可能存在不容易看到的优化机会