2013-04-02 92 views
3

我必須提取__m128i寄存器的非零值。例如,我有一個八個無符號短褲的向量。從SSE中提取_m128i寄存器的非零值

__m128i vector {40, 0, 22, 0, 0, 0, 0, 8} 

我想用最少量的SSE指令提取40,22和8。 非零值將存儲在非零值的數組中。

{40, 22, 8, more values from different vectors ... } 

它可能洗牌或有一個很好的固有提取和存儲?

+0

我們可以假設SSE 4? –

+0

是的,我們可以但我更喜歡SSSE3。 –

+0

是否需要保留非零值的順序? –

回答

2

如果你看看at this paper,作者描述瞭如何使用_mm_cmpestrm指令做基本上想要的。其算法的核心是這個(我已經稍微修改,做你想要什麼,而不是他們想要的東西):

__m128i res_v = _mm_cmpestrm(
    vector, 
    8, 
    mm_setzero_si128(), 
    8, 
    _SIDD_UWORD_OPS|_SIDD_CMP_EQUAL_ANY|_SIDD_BIT_MASK|_SIDD_NEGATIVE_POLARITY); 
int r = _mm_extract_epi32(res_v, 0); 

__m128i p = _mm_shuffle_epi8(vector, sh_mask[r]); 

如果構建了查表sh_mask在論文中描述,然後p應該有非零元素(沒有任何重新排序),然後是零元素。在r中設置的位數將告訴你非零元素的數量。

不幸的是_mm_cmpestrm在SSE4中。

+0

哇我不知道這個命令,sh_mask的技巧真的很酷。非常感謝。 –

2

基於anjruu的答案,這裏是一個已經不以任何方式被測試的SSSE3版本:

; xmm0 = input 
pxor xmm1, xmm1 
pcmpeqb xmm1, xmm0 
pmovmskb eax, xmm1 
shl eax, 4 
pshufb xmm0, [table + eax] 

table不同的是當然的,但不是很難奏效,只要記住了索引是「倒置的」 - 例如,索引0對應於不具有零,並且0xFFFF對應於全零。