C++ 确定SIMD比较寄存器位置的最快方法
我有一个已比较的SIMDC++ 确定SIMD比较寄存器位置的最快方法,c++,x86,sse,simd,avx,C++,X86,Sse,Simd,Avx,我有一个已比较的SIMD\uuu m128i寄存器,其结果如下: 0, 0, -1, -1, 0, 0, 0, 0 // in shorts 0, -1, 0, 0 // in ints 获取设置位的整数位置的最快/最便宜的方法是什么?\uuu m128i中只有一个int设置为1 例如: -1, -1, 0, 0, 0, 0, 0, 0 -> 0 0, 0, -1, -1, 0, 0, 0, 0 -> 1 0, 0, 0, 0, -1, -1, 0, 0 -> 2
\uuu m128i
寄存器,其结果如下:
0, 0, -1, -1, 0, 0, 0, 0 // in shorts
0, -1, 0, 0 // in ints
获取设置位的整数位置的最快/最便宜的方法是什么?\uuu m128i
中只有一个int设置为1
例如:
-1, -1, 0, 0, 0, 0, 0, 0 -> 0
0, 0, -1, -1, 0, 0, 0, 0 -> 1
0, 0, 0, 0, -1, -1, 0, 0 -> 2
0, 0, 0, 0, 0, 0, -1, -1 -> 3
另一个注意事项是,我只有AVX和更低版本可用,因此没有AVX2或AVX-512。我用C++和英特尔ISTIN。
编辑:这是我的当前代码:
__m128i comparableLow = _mm_set_epi32(key - 1, key - 1, key - 1, key - 1);
__m128i comparableHigh = _mm_set_epi32(key + 1, key + 1, key + 1, key + 1);
__m128i mData = _mm_loadu_si128((__m128i*)(arr));
__m128i l1 = _mm_cmpgt_epi32(mData, comparableLow);
__m128i u1 = _mm_cmplt_epi32(mData, comparableHigh);
__m128i r1 = _mm_and_si128(u1, l1);
vmovmskps
/bsf
(或tzcnt
)。看见如果这是vpcmpeqd
或vcmpps
的结果,则有dword元素,因此可以使用movmskps
获取高位位图。或者如果您总是有成对的int16\t
?IDK如果它们总是以32位块的形式出现,为什么要将其显示为int16\t
元素。可能是重复的(除了字节元素,所以可能不是)。然后对这些指令使用intrinsic,当然是让编译器发出它们<代码>无符号位图=_mm_movemask_ps(_mm_castsi128_ps(v))代码>/int pos=\u bit\u scan\u forward(位图)代码>。(或者你的编译器最喜欢的BSF本质:)那么要么你的示例从实际代码中过度简化(使用+1
/-1
而不是你的实际范围),要么你有一个bug,因为我认为它完全等同于只检查精确的相等性。但是好的,你会想要偏移量作为int
或无符号int
,所以这很好,movmskps
/bsf
正是你想要的。顺便说一句,这实际上可能不是任何东西的副本!我找不到任何其他带有[x86]代码的SO帖子:\u mm\u movemask\u ps\u BitScanForward
。movemask->bitscan是一个非常有名的习惯用法,至少我认为是这样。你会发现它最像libcmemchr
/strchr
。通常,人们只想知道是否有任何或所有元素满足某个条件,而不是哪一个,或者使用movemask
结果作为整数索引,但我真的很惊讶我没有找到该代码的现有答案。但是它的asm和C版本在一天内就发布了!如果我有时间的话,我可以打一个答案。