2012-05-12 137 views
3

使用SSE指令對兩個整數寄存器進行兩兩比較並提取相同元素的最佳方法是什麼?例如,如果a = [6 4 7 2]b = [2 4 9 2](每個寄存器包含四個32位整數),結果應該是[4 2 x x]。這個問題的另一種形式是如何獲得可用於混洗的等元素(..0101b)的二元掩碼或作爲查找用於在預計算表中混洗指令的參數的索引。使用SSE進行比較和提取

+0

減法會將相等的數字對變成0. –

回答

2

我可能會使用什麼drhirsch提出了一種變型:

int index = _mm_movemask_ps((__m128)_mm_cmp_epi32(a, b)); 

這給了你在查找僅使用兩個操作的洗牌面膜使用相同的索引。

2

不可能用一條指令提取和移動相等的元素。但平等元素的面具可以很容易地pcmpeqd來實現:

__m128i zero = _mm_set1_epi32(0); 
__m128i a = _mm_set_epi32(6, 4, 7, 2); 
__m128i b = _mm_set_epi32(2, 4, 9, 2); 

__m128i mask = _mm_cmp_epi32(a, b);  // mask is now 0, -1, 0, -1 
mask = _mm_sub_epi32(zero, mask);  // mask is now 0, 1, 0, 1 

編輯: 如果你想與洗牌常量查找表某個索引,則需要額外的操作。像

static const __m128i zero = _mm_set1_epi32(0); 
static const __m128i bits = _mm_set_epi32(1,2,4,8); 

__m128i a = _mm_set_epi32(6, 4, 7, 2); 
__m128i b = _mm_set_epi32(2, 4, 9, 2); 

__m128i bitvector = _mm_and_si128(bits, _mm_cmp_epi32(a, b)); 
bitvector = _mm_hadd_epi32(bitvector, bitvector); 
bitvector = _mm_hadd_epi32(bitvector, bitvector); 
// now a index from 0...15 is the the low 32 bit of bitvector 

有可能比使用查找表來計算的洗牌,可能直接計算使用德布魯因mulitiplication洗牌更好的算法。 OTOH如果您有4個以上的整數進行比較,則額外的4個整數將僅以一個附加phaddd爲代價。

+0

其實我的意思是一個位掩碼,可以直接用於混洗指令,或者作爲一個小索引來查找預計算表中的掩碼,也就是在這個例子中'mask ='。 .0101b = 5d'。 – user1128016

+0

@ user1128016已更新 – hirschhornsalz