【问题标题】:What is the fastest inverse of _mm_movemask_ps()?_mm_movemask_ps() 的最快倒数是多少?
【发布时间】:2019-10-30 12:22:08
【问题描述】:

How to perform the inverse of _mm256_movemask_epi8 (VPMOVMSKB)? 中,OP 要求_mm256_movemask_epi8 的倒数,但是对于SSE 的_mm_movemask_ps(),是否有更简单的版本?这是我能想到的最好的,还不错。

__m128 movemask_inverse(int x) {
    __m128 m = _mm_setr_ps(x & 1, x & 2, x & 4, x & 8);
    return _mm_cmpneq_ps(m, _mm_setzero_ps());
}

【问题讨论】:

  • 口罩应该这样吗?不是倒过来了吗?
  • @harold 你是对的。通过更改为 setr 修复
  • Peter Cordes 在is there an inverse instruction to the movemask instruction in intel avx2? 上的回答讨论了有关 AVX2 案例的许多想法。大多数这些想法也可以以某种形式用于 SSE 案例。 LUT方案和ALU方案适合你的情况。
  • 参见例如this Godbolt link
  • @wim 谢谢,这很聪明,而且性能更好一些。发布代码作为答案,我会接受。

标签: sse simd


【解决方案1】:

反向移动掩码的效率很大程度上取决于编译器。 使用 gcc 大约需要 21 instructions

但是,使用clang -std=c99 -O3 -m64 -Wall -march=nehalem,代码可以很好地矢量化, 结果其实还不错:

movemask_inverse_original:              # @movemask_inverse_original
        movd    xmm0, edi
        pshufd  xmm0, xmm0, 0           # xmm0 = xmm0[0,0,0,0]
        pand    xmm0, xmmword ptr [rip + .LCPI0_0]
        cvtdq2ps        xmm1, xmm0
        xorps   xmm0, xmm0
        cmpneqps        xmm0, xmm1
        ret
    

不过,您不需要 cvtdq2ps 整数来进行浮点转换。 在整数域中计算掩码效率更高,并且 将结果转换为(不进行转换)之后浮动。 Peter Cordes 的回答:is there an inverse instruction to the movemask instruction in intel avx2?, 讨论了有关 AVX2 案例的许多想法。 大多数这些想法也可以以某种形式用于 SSE 案例。 LUT方案和ALU方案都适合你的情况。

具有内在函数的 ALU 解决方案:

__m128 movemask_inverse_alternative(int x) {
    __m128i msk8421 = _mm_set_epi32(8, 4, 2, 1);
    __m128i x_bc = _mm_set1_epi32(x);
    __m128i t = _mm_and_si128(x_bc, msk8421);
    return _mm_castsi128_ps(_mm_cmpeq_epi32(msk8421, t));
}

使用 gcc 8.3 生成的程序集:gcc -std=c99 -O3 -m64 -Wall -march=nehalem

movemask_inverse_alternative:
  movd xmm1, edi
  pshufd xmm0, xmm1, 0
  pand xmm0, XMMWORD PTR .LC0[rip]
  pcmpeqd xmm0, XMMWORD PTR .LC1[rip]
  ret

【讨论】:

  • _mm_cmpeq_epi32() 的参数不应该是 _mm_cmpeq_epi32(x_bcmsk8421, t) 吗?此外,cmpeq 将整数设置为0xFF0x00,所以你不需要另一个_mm_and_si128(<result_from_cmpeq>, _mm_set1_epi32(1)) 吗?
  • @TillKolditz 感谢您指出我回答中的错误。我会修好它。通常00xFFFFFFFF 的结果适合进一步计算,但在某些情况下,您可能更喜欢_mm_and_ps(movemask_inverse_alternative(int x),_mm_set1_ps(1.0f)),例如。请注意,将_mm_set1_epi32(1) 转换为浮点数不会导致1.0f 的向量。
猜你喜欢
  • 1970-01-01
  • 2011-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-31
  • 2020-12-25
  • 2012-09-01
相关资源
最近更新 更多