如何使用C中的SSE内部函数计算矢量点积

Sam*_*Sam 10 c optimization sse simd vectorization

我试图将两个向量相乘,其中一个向量的每个元素乘以另一个向量的相同索引中的元素.然后,我想要对结果向量的所有元素求和,以获得一个数字.例如,对于矢量{1,2,3,4}和{5,6,7,8},计算结果如下:

1*5 + 2*6 + 3*7 + 4*8

基本上,我正在采用两个向量的点积.我知道有一个SSE命令来执行此操作,但该命令没有与之关联的内部函数.此时,我不想在我的C代码中编写内联汇编,所以我只想使用内部函数.这似乎是一个常见的计算,所以我很惊讶自己在Google上找不到答案.

注意:我正在针对特定的微架构进行优化,该架构最多支持SSE 4.2.

谢谢你的帮助.

caf*_*caf 18

GCC(至少版本4.3)包括_mm_add_psSSE4.1级内在函数,包括单精度和双精度点积:

_mm_dp_ps (__m128 __X, __m128 __Y, const int __M);
_mm_dp_pd (__m128d __X, __m128d __Y, const int __M);
Run Code Online (Sandbox Code Playgroud)

作为旧处理器的后备,您可以使用此算法创建向量的点积,<smmintrin.h>dpps:

__m128 r1 = _mm_mul_ps(a, b);
Run Code Online (Sandbox Code Playgroud)

  • 作为一个注释,我想指出使用_dp_内在函数计算Dot产品比第二种方式更慢. (8认同)

Roy*_*oyi 5

我想说最快的SSE方法是:

static inline float CalcDotProductSse(__m128 x, __m128 y) {
    __m128 mulRes, shufReg, sumsReg;
    mulRes = _mm_mul_ps(x, y);

    // Calculates the sum of SSE Register - /sf/answers/2468901851/
    shufReg = _mm_movehdup_ps(mulRes);        // Broadcast elements 3,1 to 2,0
    sumsReg = _mm_add_ps(mulRes, shufReg);
    shufReg = _mm_movehl_ps(shufReg, sumsReg); // High Half -> Low Half
    sumsReg = _mm_add_ss(sumsReg, shufReg);
    return  _mm_cvtss_f32(sumsReg); // Result in the lower part of the SSE Register
}
Run Code Online (Sandbox Code Playgroud)

我遵循了- 在x86上进行水平浮点矢量求和的最快方法