use*_*108 1 c x86 simd avx sse4
如您所知,前两个是特定于 AVX 的内在函数,第二个是 SSE4.1 内在函数。两组内在函数都可用于检查 2 个浮点向量的相等性。我的具体用例是:
_mm_cmpeq_ps或_mm_cmpeq_pd,然后是_mm_testc_ps或_mm_testc_pd在结果上,使用适当的掩码但是 AVX 为“传统”内在函数提供了等价物,因此_mm_testc_si128在将结果转换为__m128i. 我的问题是,这两个用例中的哪一个会导致更好的性能,以及我在哪里可以找到 AVX 提供了哪些旧的 SSE 指令。
哎呀,我没有仔细阅读问题。您正在谈论在cmpeqps. 他们总是比movmskps / test你已经有了口罩要慢。 cmpps/ptest / jcc是 4 uop。 cmpps/ movmskps eax, xmm0/ test eax,eax/ jnz3个微指令。(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
Run Code Online (Sandbox Code Playgroud)
这是完全免费的。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(在符号位或完整寄存器上),这不会告诉您它们是否相等,甚至符号位是否相等。
请注意,即使检查浮点数的按位相等(with pcmpeqd)也与cmpeqps(实现 C 的==运算符)不同,因为-0.0不是按位等于0.0. 两个按位相同的 NaN 彼此不相等。如果一个或两个操作数是 ,则比较是无序的(这意味着不相等)NaN。