在我当前的项目中,我必须比较 128 位值(实际上是 md5 哈希),我认为可以通过使用 SSE 指令来加速比较。我的问题是我无法找到关于 SSE 说明的好的文档;我正在寻找一个 128 位整数比较指令,让我知道一个散列是否更大、更小或等于另一个。这样的指令存在吗?
PS:目标机器是带有SSE2指令的x86_64服务器;我也对同一工作的 NEON 指令感兴趣。
在我当前的项目中,我必须比较 128 位值(实际上是 md5 哈希),我认为可以通过使用 SSE 指令来加速比较。我的问题是我无法找到关于 SSE 说明的好的文档;我正在寻找一个 128 位整数比较指令,让我知道一个散列是否更大、更小或等于另一个。这样的指令存在吗?
PS:目标机器是带有SSE2指令的x86_64服务器;我也对同一工作的 NEON 指令感兴趣。
SSE 或 NEON 指令集中没有 128 位整数比较指令。
SSE4.1 添加了向量 64 位整数比较:PCMPEQQ 和 PCMPGTQ,但由于它们的实现方式,将它们中的两个组合成 128 位比较并不简单。
在 x86_64 上完成 128 位比较的首选方法是在高位字上使用 64 位比较,然后仅在高位字比较相等时对低位字进行额外的 64 位比较:
cmp {ahi}, {bhi}
jne 0f
cmp {alo}, {blo}
0: // flags are now set as though a comparison of unsigned 128-bit values
// was performed; signed comparisons are a bit different.
在 ARM 上,通常的习惯用法是逐字进行条件比较的序列,以根据需要设置标志。
a
实际上,两个值的128 位比较b
可以使用 SSE 4.1 与两条指令和一个备用寄存器之前设置为零。
在 x86 程序集中,使用旧版 128 位 SSE:
pxor %xmm2, %xmm2 # set xmm2 to zero. Should be moved out of the loop.
# compare %xmm0 to %xmm1 for equality
pxor %xmm0, %xmm1 # xmm1 is zero if both operands are equal
ptest %xmm2, %xmm1 # test not(xmm2) and xmm1. If any bit in xmm1 is set
jc equal # the carry flag is cleared.
not_equal:
...
equal:
首选在 C 中使用内部函数,因为它们将自动受益于 AVX 3 操作数语法,这实际上节省了大量的 SSE 寄存器移动。
static const __m128i zero = {0};
inline bool compare128(__m128i a, __m128i b) {
__m128i c = _mm_xor_si128(a, b);
return _mm_testc_si128(zero, c);
}
这编译成与上面类似的东西,特别是 bool 临时被折叠并直接使用进位标志。
PCMPGT 不会比较整个 128 位,它总是使用较小的单元并产生单独的结果。此外,它适用于有符号值,这使事情进一步复杂化。
如果您在 64 位模式下运行,我认为使用两个本机 64 位减法或比较会最快。
不知道为什么找不到文档,全部都在intel 指令集参考中。