1

如您所知,前两个是特定于 AVX 的内在函数,第二个是 SSE4.1 内在函数。两组内在函数都可用于检查 2 个浮点向量是否相等。我的具体用例是:

  • _mm_cmpeq_ps_mm_cmpeq_pd, 后跟
  • _mm_testc_ps_mm_testc_pd在结果上,使用适当的掩码

但是 AVX 提供了“遗留”内在函数的等价物,所以我可以在_mm_testc_si128将结果转换为__m128i. 我的问题是,这两个用例中的哪一个会带来更好的性能,以及我在哪里可以找到 AVX 提供了哪些旧版 SSE 指令。

4

1 回答 1

5

糟糕,我没有仔细阅读问题。你说的是在cmpeqps. 他们总是比movmskps / test你已经有面具要慢。 cmpps/ptest / jcc是 4 微秒。 cmpps///是movmskps eax, xmm03微秒test eax,eaxjnz(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,但它们的运行方式相同。)。

有关指南的链接,请参阅 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

于 2016-03-04T08:31:07.343 回答