SIMD零矢量测试

时间:2015-03-14 17:18:09

标签: sse simd neon avx sse2

是否存在快速检查SIMD向量是否为零向量(所有组件等于+ -zero)的方法。我目前正在使用一种算法,使用在log2(N)时间内运行的移位,其中N是向量的维数。有没有更快的东西?请注意,我的问题比提出的答案更广泛(标签),它引用了所有类型的向量(整数,浮点数,双精度......)。

1 个答案:

答案 0 :(得分:1)

如果要测试浮点数为+/- 0.0,则可以检查除符号位之外的所有位为零。除符号位之外的任何位置都意味着浮点数不为零。 (http://www.h-schmidt.net/FloatConverter/IEEE754.html

Agner Fog的asm optimization guide指出你可以使用整数指令测试浮点数或加倍为零:

; Example 17.4b
mov  eax, [rsi]
add  eax, eax   ; shift out the sign bit
jz   IsZero

对于向量,使用带有符号位掩码的ptest比使用paddd去掉符号位要好。实际上,test [rsi], $0x7fffffff可能比Agner Fog的加载/添加序列更有效,但32位立即可能会阻止英特尔微融合的负载,并且可能具有更大的代码大小。

x86 PTEST(SSE4.1)执行按位AND并根据结果设置标志。

movdqa xmm0, [mask]
.loop:
ptest  xmm0, [rsi+rcx]
jnz    nonzero
add    rcx, 16  # count up towards zero
jl     .loop    # with rsi pointing to past the end of the array
...
nonzero:

cmov可能有助于使用ptest设置的标记。

IDK如果可以使用没有设置零标志的循环计数器指令,那么你可以使用一个跳转指令进行两个测试。可能不是。并且用于合并标志的额外uop(或早期CPU上的部分标志停止)将抵消该好处。

@Iwillnotexist Idonotexist:你对OP的评论之一:你不能只先移动pcmpeq,或cmpps。非零位可能不在高位!你可能知道这一点,但你的一条评论似乎已经废除了。

我确实喜欢在实际测试之前将多个值进行ORing的想法。你是对的,符号位会与其他符号位进行或运算,然后你就像你一次测试一样符号一样忽略它们。在POR之前PTEST 4或8个向量的循环可能会更快。 (PTEST是2 uops,不能与jcc进行宏观融合。)