两个整数寄存器的成对比较和使用SSE指令提取相等元素的最佳方法是什么?例如,如果a = [6 4 7 2]
和b = [2 4 9 2]
(每个寄存器包含四个32位整数),则结果应为[4 2 x x]
。此问题的另一种形式是如何获取可用于混洗的相等元素(..0101b
)的二进制掩码,或者作为索引来查找预先计算表中的混洗指令的参数。
答案 0 :(得分:3)
无法通过一条指令提取和移动相等的元素。但是使用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
编辑: 如果你想要一个带有shuffle常量的查找表的索引,你需要额外的操作。像
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
可能有比使用查找表来计算shuffle更好的算法,可能使用De Bruijn mulitiplication直接计算shuffle。 OTOH如果你有超过4个整数进行比较,额外的4个int只会以一个额外phaddd
为代价。
答案 1 :(得分:2)
我可能会使用drhirsch
建议的变体:
int index = _mm_movemask_ps((__m128)_mm_cmp_epi32(a, b));
这为您提供了与仅使用两个操作查找随机掩码相同的索引。