【发布时间】:2013-06-08 15:25:29
【问题描述】:
我需要使用 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);
}
但我用 gcc 4.9 (experimental) -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
我想知道为什么 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
【问题讨论】:
-
你是在循环中调用这个函数还是真的只是在做一个 4 点乘积?如果您在循环中执行此操作,请查看以下答案:stackoverflow.com/a/17001365/253056 并将
_mm_hadd_ps替换为标量代码。 -
我的编译器(不是 gcc)生成了同样的代码,奇怪的巧合。我没有看到任何暗示如果 SHUFPS 使用两个不同的寄存器可能会更快。也许它在旧处理器上。
-
我的处理器不是那么旧:i5-2450M(所以它有 sse4.2 和 avx,但它是用于“便携式”版本)。我只是在编译我给出的代码:gcc dot.c -O3 -S -o dot.s。所以不涉及循环。
-
编译器不注意你的处理器。代码还需要在另一台机器上运行。
-
@HansPassant gcc 如果你像他一样通过
-march=native