我必須提取__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 ... }
它可能洗牌或有一個很好的固有提取和存儲?
我必須提取__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 ... }
它可能洗牌或有一個很好的固有提取和存儲?
如果你看看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中。
哇我不知道這個命令,sh_mask的技巧真的很酷。非常感謝。 –
基於anjruu的答案,這裏是一個已經不以任何方式被測試的SSSE3版本:
; xmm0 = input
pxor xmm1, xmm1
pcmpeqb xmm1, xmm0
pmovmskb eax, xmm1
shl eax, 4
pshufb xmm0, [table + eax]
的table
不同的是當然的,但不是很難奏效,只要記住了索引是「倒置的」 - 例如,索引0對應於不具有零,並且0xFFFF對應於全零。
我們可以假設SSE 4? –
是的,我們可以但我更喜歡SSSE3。 –
是否需要保留非零值的順序? –