糟糕,我没有仔细阅读问题。你说的是在cmpeqps
. 他们总是比movmskps / test
你已经有面具要慢。 cmpps
/ptest / jcc
是 4 微秒。 cmpps
///是movmskps eax, xmm0
3微秒test eax,eax
。jnz
(test/jnz 融合成一个 uop)。此外,没有一条指令是多指令的,因此没有解码瓶颈。
只有在可以充分利用 AND 或 ANDN 操作来避免更早的步骤时才使用ptest
/ 。在比较与替代方案vtestps/pd
之前,我已经发布了答案。ptest
我想我确实找到了一个ptest
成功的案例,但它很难使用。是的,找到了:有人想要一个适用于 NaN == NaN 的 FP 比较。这是我唯一一次发现ptest
.
如果比较结果的高元素是“垃圾”,那么您仍然可以通过以下方式廉价地忽略它movmskps
:
_mm_movemask_ps(vec) & 0b0111 == 0 // tests for none of the first three being true
这是完全免费的。x86test
指令的工作原理很像ptest
:您可以将其与立即掩码一起使用,而不是针对自身测试寄存器。(它实际上有一个很小的成本:一个额外的机器代码字节,因为test eax, 3
比 长一个字节test eax, eax
,但它们的运行方式相同。)。
有关指南的链接,请参阅x86 wiki(Agner Fog 的指南非常适合在指令级别进行性能分析)。每个旧版 SSE 指令都有一个 AVX 版本,但有些只有 128 位宽。它们都得到一个额外的操作数(因此 dest 不必是 src regs 之一),这节省了mov
复制寄存器的指令。
回答你没有问的问题:
两者都_mm_testc_ps
不能_mm_testc_si128
用于比较浮点数是否相等。 vtestps
类似于ptest
,但仅对每个浮点元素的符号位进行操作。
它们都计算(~x) & y
(在符号位上或在完整寄存器上),这不会告诉您它们是否相等,甚至符号位是否相等。
请注意,即使检查浮点数的按位相等(使用pcmpeqd
)也与cmpeqps
(实现 C 的==
运算符)不同,因为-0.0
按位不等于0.0
. 并且两个按位相同的 NaN 彼此不相等。如果一个或两个操作数是 ,则比较是无序的(这意味着不相等)NaN
。