如何横向汇总__m256?

Ben*_*Uri 11 sse vectorization intrinsics avx

我想__m256使用AVX指令水平地对矢量的分量求和.在SSE我可以使用

_mm_hadd_ps(xmm,xmm);
_mm_hadd_ps(xmm,xmm);
Run Code Online (Sandbox Code Playgroud)

在向量的第一个组件处获得结果,但这不能与函数(_mm256_hadd_ps)的256位版本一起扩展.

计算__m256向量水平和的最佳方法是什么?

Mar*_*han 8

对于Intel Sandy/Ivy Bridge和AMD Bulldozer,此版本应该是最佳的:

// x = ( x7, x6, x5, x4, x3, x2, x1, x0 )
float sum8(__m256 x) {
    // hiQuad = ( x7, x6, x5, x4 )
    const __m128 hiQuad = _mm256_extractf128_ps(x, 1);
    // loQuad = ( x3, x2, x1, x0 )
    const __m128 loQuad = _mm256_castps256_ps128(x);
    // sumQuad = ( x3 + x7, x2 + x6, x1 + x5, x0 + x4 )
    const __m128 sumQuad = _mm_add_ps(loQuad, hiQuad);
    // loDual = ( -, -, x1 + x5, x0 + x4 )
    const __m128 loDual = sumQuad;
    // hiDual = ( -, -, x3 + x7, x2 + x6 )
    const __m128 hiDual = _mm_movehl_ps(sumQuad, sumQuad);
    // sumDual = ( -, -, x1 + x3 + x5 + x7, x0 + x2 + x4 + x6 )
    const __m128 sumDual = _mm_add_ps(loDual, hiDual);
    // lo = ( -, -, -, x0 + x2 + x4 + x6 )
    const __m128 lo = sumDual;
    // hi = ( -, -, -, x1 + x3 + x5 + x7 )
    const __m128 hi = _mm_shuffle_ps(sumDual, sumDual, 0x1);
    // sum = ( -, -, -, x0 + x1 + x2 + x3 + x4 + x5 + x6 + x7 )
    const __m128 sum = _mm_add_ss(lo, hi);
    return _mm_cvtss_f32(sum);
}
Run Code Online (Sandbox Code Playgroud)

  • 这就是为什么我说"奇怪的角落案例"(它们非常罕见,而且非常奇怪). (2认同)

Ben*_*Uri 5

这可以通过以下代码完成:

ymm2 = _mm256_permute2f128_ps(ymm , ymm , 1);
ymm = _mm256_add_ps(ymm, ymm2);
ymm = _mm256_hadd_ps(ymm, ymm);
ymm = _mm256_hadd_ps(ymm, ymm);
Run Code Online (Sandbox Code Playgroud)

但可能有更好的解决方案。

  • 我注意到排列+添加也可以出现在两个哈德*之后。 (2认同)