水平求和SSE无符号字节向量的最快方法

use*_*848 5 c++ x86 sse simd

我需要水平添加一个__m128i16 x epi8值.XOP指令会使这个变得微不足道,但我没有这些指令.

目前的方法是:

hd = _mm_hadd_epi16(_mm_cvtepi8_epi16(sum), _mm_cvtepi8_epi16(_mm_shuffle_epi8(sum, swap)));
hd = _mm_hadd_epi16(hd, hd);
hd = _mm_hadd_epi16(hd, hd);
Run Code Online (Sandbox Code Playgroud)

SSE4.1有更好的方法吗?

Pau*_*l R 8

您可以使用SSE2 _mm_sad_epu8(psadbw)执行此操作,例如:

inline uint32_t _mm_sum_epu8(const __m128i v)
{
    __m128i vsum = _mm_sad_epu8(v, _mm_setzero_si128());
    return _mm_extract_epi16(vsum, 0) + _mm_extract_epi16(vsum, 4);
}
Run Code Online (Sandbox Code Playgroud)

  • 编译器无法将 `_mm_extract_epi16(vsum, 0)` 优化为 `movd` - 它们没有意识到低位 dword 的高 2 个字节将为 0,因此它们实际上使用 `pextrw eax, xmm0, 0`。https://godbolt.org/z/TMb8rc1j4。使用 `_mm_cvtsi128_si32(vsum)` 来保存 shuffle uop。我为你解决了这个问题。 (2认同)