我需要一种方法来比较C ++中类型为__m128i
的任何值之间的总顺序。顺序的类型无关紧要,只要它在类型__m128i
的所有值之间建立总顺序即可。因此,该比较可能不及128位整数之间的比较,或完全可以提供总顺序的其他东西。
我尝试使用__m128i
运算符,但是没有返回<
,而是似乎比较了bool
(即SIMD)的矢量分量:
__m128i
另一种可能性是使用#include <emmintrin.h>
inline bool isLessThan(__m128i a, __m128i b) noexcept {
// error: cannot convert '__vector(2) long int' to 'bool' in return
return a < b;
}
/ memcmp
或类似的方法,但这很可能不是最佳选择。针对至少具有SSE4.2和AVX2的现代Intel x86-64 CPU,我是否可以使用任何内在函数/指令进行此类比较?怎么做?
PS:已经问过类似的问题来检查相等性,而不是顺序:
答案 0 :(得分:5)
你在这里。
inline bool isLessThan( __m128i a, __m128i b )
{
/* Compare 8-bit lanes for ( a < b ), store the bits in the low 16 bits of the
scalar value: */
const int less = _mm_movemask_epi8( _mm_cmplt_epi8( a, b ) );
/* Compare 8-bit lanes for ( a > b ), store the bits in the low 16 bits of the
scalar value: */
const int greater = _mm_movemask_epi8( _mm_cmpgt_epi8( a, b ) );
/* It's counter-intuitive, but this scalar comparison does the right thing.
Essentially, integer comparison searches for the most significant bit that
differs... */
return less > greater;
}
顺序不理想’coz pcmpgtb
将这些字节视为带符号整数,但是您说这对用例并不重要。
更新:这里的版本稍慢,排序顺序为uint128_t
。
// True if a < b, for unsigned 128 bit integers
inline bool cmplt_u128( __m128i a, __m128i b )
{
// Flip the sign bits in both arguments.
// Transforms 0 into -128 = minimum for signed bytes,
// 0xFF into +127 = maximum for signed bytes
const __m128i signBits = _mm_set1_epi8( (char)0x80 );
a = _mm_xor_si128( a, signBits );
b = _mm_xor_si128( b, signBits );
// Now the signed byte comparisons will give the correct order
const int less = _mm_movemask_epi8( _mm_cmplt_epi8( a, b ) );
const int greater = _mm_movemask_epi8( _mm_cmpgt_epi8( a, b ) );
return less > greater;
}
我们通过将无符号输入范围移位到有符号(通过翻转高位=减去128)来建立无符号比较。