C内在函数,SSE2点积和gcc -O3生成的汇编

mat*_*tch 4 c assembly sse

我需要使用SSE2编写一个点积(没有_mm_dp_ps也没有_mm_hadd_ps):

#include <xmmintrin.h>

inline __m128 sse_dot4(__m128 a, __m128 b)
{
    const __m128 mult = _mm_mul_ps(a, b);
    const __m128 shuf1 = _mm_shuffle_ps(mult, mult, _MM_SHUFFLE(0, 3, 2, 1));
    const __m128 shuf2 = _mm_shuffle_ps(mult,mult, _MM_SHUFFLE(1, 0, 3, 2));
    const __m128 shuf3 = _mm_shuffle_ps(mult,mult, _MM_SHUFFLE(2, 1, 0, 3));

    return _mm_add_ss(_mm_add_ss(_mm_add_ss(mult, shuf1), shuf2), shuf3);
}
Run Code Online (Sandbox Code Playgroud)

但我看了生成的汇编程序与gcc 4.9(实验)-O3,我得到:

    mulps   %xmm1, %xmm0
    movaps  %xmm0, %xmm3         //These lines
    movaps  %xmm0, %xmm2         //have no use
    movaps  %xmm0, %xmm1         //isn't it ?
    shufps  $57, %xmm0, %xmm3
    shufps  $78, %xmm0, %xmm2
    shufps  $147, %xmm0, %xmm1
    addss   %xmm3, %xmm0
    addss   %xmm2, %xmm0
    addss   %xmm1, %xmm0
    ret
Run Code Online (Sandbox Code Playgroud)

我想知道为什么gcc在xmm1,2和3中复制xmm0 ...这是我使用标志得到的代码:-march = native(看起来更好)

    vmulps  %xmm1, %xmm0, %xmm1
    vshufps $78, %xmm1, %xmm1, %xmm2
    vshufps $57, %xmm1, %xmm1, %xmm3
    vshufps $147, %xmm1, %xmm1, %xmm0
    vaddss  %xmm3, %xmm1, %xmm1
    vaddss  %xmm2, %xmm1, %xmm1
    vaddss  %xmm0, %xmm1, %xmm0
    ret
Run Code Online (Sandbox Code Playgroud)

Bre*_*ale 5

这是一个只使用原始SSE指令的点积,它也会在每个元素上调整结果:

inline __m128 sse_dot4(__m128 v0, __m128 v1)
{
    v0 = _mm_mul_ps(v0, v1);

    v1 = _mm_shuffle_ps(v0, v0, _MM_SHUFFLE(2, 3, 0, 1));
    v0 = _mm_add_ps(v0, v1);
    v1 = _mm_shuffle_ps(v0, v0, _MM_SHUFFLE(0, 1, 2, 3));
    v0 = _mm_add_ps(v0, v1);

    return v0;
}
Run Code Online (Sandbox Code Playgroud)

它是5个SIMD指令(而不是7个),但没有隐藏延迟的真正机会.任何元素都会保存结果,例如,float f = _mm_cvtss_f32(sse_dot4(a, b);

haddps指令具有非常糟糕的延迟.使用SSE3:

inline __m128 sse_dot4(__m128 v0, __m128 v1)
{
    v0 = _mm_mul_ps(v0, v1);

    v0 = _mm_hadd_ps(v0, v0);
    v0 = _mm_hadd_ps(v0, v0);

    return v0;
}
Run Code Online (Sandbox Code Playgroud)

虽然它只有3条SIMD指令,但速度可能较慢.如果您一次可以执行多个点积,则可以在第一种情况下交错指令.在最近的微架构上,Shuffle非常快.

  • @matovitch*"addss必须比addps快"* - SSE的重点不是"addps"比*addss慢*不慢吗? (4认同)