Vector 苏格兰和南方能源公司没有';t匹配串行浮点加法

Vector 苏格兰和南方能源公司没有';t匹配串行浮点加法,vector,comparison,precision,sse,Vector,Comparison,Precision,Sse,以下是让我感到悲伤的测试程序: #include <xmmintrin.h> #include <stdio.h> inline float _mm_hadd_ps(const __m128 v) { const __m128 x = _mm_add_ps(v, _mm_movehl_ps(v, v)), xx = _mm_add_ss(x, _mm_shuffle_ps(x, x, 1)); float __attri

以下是让我感到悲伤的测试程序:

#include <xmmintrin.h>
#include <stdio.h>

inline float
_mm_hadd_ps(const __m128 v)
{
    const __m128
        x = _mm_add_ps(v, _mm_movehl_ps(v, v)),
        xx = _mm_add_ss(x, _mm_shuffle_ps(x, x, 1));

    float __attribute__((aligned(16))) s;
    _mm_store_ss(&s, xx);
    return s;
}


int
main(void)
{
    const float __attribute__((aligned(16))) d[] = { 
        4.0763611794e+00, 1.1881252751e-02, 4.9195003510e+00, 0.0000000000e+00
    };  

    const float x = _mm_hadd_ps(_mm_load_ps(d));
    const float y = d[0] + d[1] + d[2] + d[3];

    printf("diff: %.10f\n", x - y); 
    return 0;
}
我从中得到的输出是:

diff: -0.0000009537
我知道扩展精度算法的问题,因此
mfpmath=sse
。查看汇编代码,串行加法实际上是使用
addss
完成的,而最终减法是使用
subss
完成的

在这一点上,我很难解释这种差异是从哪里来的。如果有人能解释一下这种情况,我将不胜感激


如果有什么不同,我使用的是GCC4.3.4。(编辑:在AMD Opteron 2218+Gentoo Linux上)

FWIW gcc 4.2和Intel ICC 11.1给出了完全相同的结果。我怀疑这只是由于执行加法的顺序不同而导致的累积舍入误差的不同。

看起来您是正确的。将总和更改为
(d[0]+d[2])+(d[1]+d[3])
将差值减小为零。
diff: -0.0000009537