2011-09-26 208 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開始;可能會有優化機會不容易看到在這個低水平