_mm_cmpgt_epi64 内在如何工作
How does the _mm_cmpgt_epi64 intrinsic work
我正在使用 _mm_cmpgt_epi64
内在函数来实现 128 位加法,然后是 256 位加法。
看着这个内在的东西的结果让我感到困惑。
我不明白为什么计算出的掩码是这样的。
const __m128i mask = _mm_cmpgt_epi64(bflip, sumflip);
这是我的调试器的输出:
(lldb) p/x bflip
(__m128i) = (0x00000001, 0x80000000, 0x00000000, 0x80000000)
(lldb) p/x sumflip
(__m128i) = (0x00000000, 0x80000000, 0xffffffff, 0x7fffffff)
(lldb) p/x mask
(__m128i) = (0xffffffff, 0xffffffff, 0x00000000, 0x00000000)
对于第一个 64 位通道 (63:0
) 我没问题。但是为什么第二条车道(127:64
)也不是满满的?
在我看来 0x8000000000000000
> 0x7fffffffffffffff
.
您似乎是以 32 位块而不是 64 位块的形式打印它,这很奇怪。
但无论如何,这是一个 signed two's complement integer compare, as documented in the manual: http://felixcloutier.com/x86/PCMPGTQ.html
0x8000000000000000
是最大的负数64位整数,而0x7fffffffffffffff
是最大的正数。
如果你想要一个无符号的比较,你需要通过翻转它们的符号位来改变两个输入的范围。从逻辑上讲,这是从 0..2^64-1 减去 2^63 到 -2^63 .. 2^63-1。但是我们可以使用更高效的 XOR 来实现,因为 XOR 是无进位加法,并且 carry/borrow-out 从寄存器末尾开始。
const __m128i rangeshift = _mm_set1_epi64x(0x8000000000000000);
const __m128i mask = _mm_cmpgt_epi64(_mm_xor_si128(bflip, rangeshift), _mm_xor_si128(sumflip, rangeshift));
或使用AVX512F__mmask8 _mm512_cmp[eq|ge|gt|le|lt|neq]_epu64_mask( __m512i a, __m512i b)
我正在使用 _mm_cmpgt_epi64
内在函数来实现 128 位加法,然后是 256 位加法。
看着这个内在的东西的结果让我感到困惑。
我不明白为什么计算出的掩码是这样的。
const __m128i mask = _mm_cmpgt_epi64(bflip, sumflip);
这是我的调试器的输出:
(lldb) p/x bflip
(__m128i) = (0x00000001, 0x80000000, 0x00000000, 0x80000000)
(lldb) p/x sumflip
(__m128i) = (0x00000000, 0x80000000, 0xffffffff, 0x7fffffff)
(lldb) p/x mask
(__m128i) = (0xffffffff, 0xffffffff, 0x00000000, 0x00000000)
对于第一个 64 位通道 (63:0
) 我没问题。但是为什么第二条车道(127:64
)也不是满满的?
在我看来 0x8000000000000000
> 0x7fffffffffffffff
.
您似乎是以 32 位块而不是 64 位块的形式打印它,这很奇怪。
但无论如何,这是一个 signed two's complement integer compare, as documented in the manual: http://felixcloutier.com/x86/PCMPGTQ.html
0x8000000000000000
是最大的负数64位整数,而0x7fffffffffffffff
是最大的正数。
如果你想要一个无符号的比较,你需要通过翻转它们的符号位来改变两个输入的范围。从逻辑上讲,这是从 0..2^64-1 减去 2^63 到 -2^63 .. 2^63-1。但是我们可以使用更高效的 XOR 来实现,因为 XOR 是无进位加法,并且 carry/borrow-out 从寄存器末尾开始。
const __m128i rangeshift = _mm_set1_epi64x(0x8000000000000000);
const __m128i mask = _mm_cmpgt_epi64(_mm_xor_si128(bflip, rangeshift), _mm_xor_si128(sumflip, rangeshift));
或使用AVX512F__mmask8 _mm512_cmp[eq|ge|gt|le|lt|neq]_epu64_mask( __m512i a, __m512i b)