【问题标题】:Can FP compares like SSE2 _mm_cmpeq_pd be used to compare 64 bit integers?FP 比较像 SSE2 _mm_cmpeq_pd 可以用来比较 64 位整数吗?
【发布时间】:2022-01-11 04:23:05
【问题描述】:

FP 比较像 SSE2 _mm_cmpeq_pd / AVX _mm_cmp_pd 可以用来比较 64 位整数吗?

这个想法是模拟丢失的_mm_cmpeq_epi64,它类似于_mm_cmpeq_epi8_mm_cmpeq_epi16_mm_cmpeq_epi32

担心的是我不确定比较是按位进行还是专门处理浮点数,比如 NAN 值总是不相等的。

【问题讨论】:

  • 不是直接的,因为NaN != NaN-0.0 == 0.0。可能通过一些巧妙的小技巧可以实现。
  • @chtz,谢谢,这对我来说已经足够了,如果你愿意,你可以把这个作为答案发布,我不会去玩聪明的小玩意儿,那么用_mm_cmpeq_epi32 会更容易。
  • 我认为这应该适用于任何“正常”c:_mm_cmpeq_pd(c, _mm_xor_pd(c, _mm_xor_pd(a,b)));。虽然有趣的是,gcc 优化了 c(但您可以通过混合 xor 操作的顺序来欺骗它):godbolt.org/z/jraEq9seb

标签: simd sse avx sse2


【解决方案1】:

AVX 意味着 SSE4.1 的可用性pcmpeqq 可用,在这种情况下您应该只使用_mm_cmpeq_epi64

FP 比较对待 NaN != NaN 和 -0.0 == +0.0,如果在 MXCSR 中设置了 DAZ,则将任何小整数视为零。 (因为 exponent = 0 意味着它表示非正规,并且非正规化为零模式将它们在输入上完全视为零,以避免对任何微架构上的任何操作(包括比较)可能造成的速度损失。IIRC,现代微架构没有对低于正常值的输入进行比较的惩罚,但对于其他一些操作仍然如此。无论如何,使用-ffast-math 构建的程序会在启动时为主线程设置 FTZ 和 DAZ。)

所以 FP 比较实际上不能用于整数,除非您知道将设置部分但不是全部的 bits [62:52] (inclusive)


使用pcmpeqd (_mm_cmpeq_epi32) 比破解一些 FP 位操作要多得多。 (尽管 @chtz 在 cmets 中建议您可以使用 xorpd 执行 42.0 == (42.0 ^ (a^b)),只要编译器不优化常量并与 0.0 进行比较。这是没有 -ffast-math 的 GCC 错误)。

如果您想要一个条件,例如 at-least-one-match,那么您需要确保 64 位元素的两半都匹配,例如 mask & (mask<<1) 上的 movmskps 结果,它可以编译为 lea /test。 (您可以在 pmovmskb 结果上使用 mask & (mask<<4),但这效率稍低,因为 LEA 复制和移位只能移位 0..3。)

当然,“全匹配”并不关心元素大小,因此您可以在任何比较结果上使用_mm_movemask_epi8,然后对照0xFFFF 进行检查。

如果您想将它用于与 and/andnot/or 的混合,您可以 pshufd / pand 在 64 位元素内交换一半。 (如果你喂的是pblendvbblendvpd,这意味着SSE4.1 可用,所以你应该使用pcmpeqq。)

要模拟的成本更高的是 SSE4.2 pcmpgtq,尽管我认为 GCC 和/或 clang 确实知道在自动矢量化时如何模拟它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-22
    • 2016-01-01
    • 1970-01-01
    • 2017-04-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多