- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
如您所知,前两个是特定于 AVX 的内部函数,第二个是 SSE4.1 内部函数。两组内在函数均可用于检查 2 个浮点 vector 是否相等。我的具体用例是:
_mm_cmpeq_ps
或 _mm_cmpeq_pd
,后跟_mm_testc_ps
或 _mm_testc_pd
结果,带有适当的掩码但 AVX 为“遗留”内在函数提供了等效项,因此在将结果转换为 __m128i
之后,我可以使用 _mm_testc_si128
。我的问题是,这两个用例中的哪一个会带来更好的性能,以及我在哪里可以找到 AVX 提供的遗留 SSE 指令。
最佳答案
糟糕,我没有仔细阅读问题。您是在谈论在 cmpeqps
之后使用这些。如果您已经有了面具,它们总是比 movmskps/test
慢。 cmpps
/ptest/jcc
是 4 微指令。 cmpps
/movmskps eax, xmm0
/test eax,eax
/jnz
是 3 微指令。 (test/jnz 融合成一个 uop)。此外,所有指令都不是多 uop,因此没有解码瓶颈。
只有在您可以充分利用 AND 或 ANDN 操作以避免更早的步骤时才使用 ptest
/vtestps/pd
。在将 ptest
与替代方案进行比较之前,我已经发布了答案。我想我确实找到了一个案例,其中 ptest
是一个胜利,但它很难使用。是的,found it: someone wanted an FP compare that was true for NaN == NaN .这是我发现 ptest
的进位标志结果的唯一一次使用。
如果比较结果的高位元素是“垃圾”,那么您仍然可以使用 movmskps
廉价地忽略它:
_mm_movemask_ps(vec) & 0b0111 == 0 // tests for none of the first three being true
这是完全免费的。 x86 test
指令的工作方式与 ptest
非常相似:您可以将它与直接掩码一起使用,而不是针对自身测试寄存器。 (它实际上有一个很小的成本:一个额外的机器代码字节,因为 test eax, 3
比 test eax, eax
长一个字节,但它们运行相同。) .
参见 x86 wiki 指南的链接(Agner Fog 的指南非常适合指令级别的性能分析)。 每个 遗留 SSE 指令都有一个 AVX 版本,但有些只有 128 位宽。它们都获得了一个额外的操作数(因此 dest 不必是 src regs 之一),这节省了复制寄存器的 mov
指令。
回答一个你没有问过的问题:
_mm_testc_ps
和 _mm_testc_si128
都不能用于比较 float 是否相等。 vtestps
类似于 ptest
,但只对每个 float 元素的符号位进行操作。
它们都计算 (~x) & y
(在符号位或完整寄存器上),这不会告诉你它们是否相等,甚至符号位是否相等.
请注意,即使检查 float 的按位相等性(使用 pcmpeqd
)也不同于 cmpeqps
(它实现了 C 的 ==
运算符),因为 -0.0
按位不等于 0.0
。并且两个按位相同的 NaN 彼此不相等。如果其中一个或两个操作数是 NaN
,则比较是无序的(这意味着不相等)。
关于c - _mm_testc_ps 和 _mm_testc_pd 与 _mm_testc_si128,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35790710/
如您所知,前两个是特定于 AVX 的内部函数,第二个是 SSE4.1 内部函数。两组内在函数均可用于检查 2 个浮点 vector 是否相等。我的具体用例是: _mm_cmpeq_ps 或 _mm_c
我是一名优秀的程序员,十分优秀!