2011-09-26 140 views
1

我在SSE2 intrinsincs中具有以下代码。它处理来自Kinect的输入。将SSE2移植到ARM NEON intrinsincs

__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)){ ... } 

这基本上解包11 uint8_t(R0-R10)至8 uint16_t在SSE寄存器(mmask指定是恒定的,先前创建的)。然后它将两个数组中的对应元素加载两个寄存器作为边界。它检查它们并创建一个寄存器,其中的元素不符合标准清零。然后存储它们并进一步处理每个元素。当没有任何元素通过时,movemask可以作为一个很好的优化,在这种情况下,处理可以被跳过。

这很好,现在我想将它移植到NEON。除了两个部分外,大部分内容都很简单。看看SSE2代码中的汇编输出(gcc),我发现它不是在_mm_setr_epi16中执行8个uint16_t移动,而是将它们转换为uint32_t,最后执行4个移动。这似乎是有效的,因为编译器照顾它,我没有改变代码。我是否应该在NEON情况下手动应用?而不是8 vsetq_lane_u16做转移,并执行4 vsetq_lane_u32?我是否会遇到任何问题,是否值得?

最后一部分是movemask,因为我还没有找到相应的东西。任何人都可以提出建议

回答

1

我宁愿从简单的C代码而不是SSE2开始;可能会有优化机会不容易看到在这个低水平