2011-05-02 27 views
2

這裏有一個是給我的悲痛測試程序: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 __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; 
} 

我與它編譯如下:

gcc -Wall -msse2 -mfpmath=sse -O0 -g -ggdb sse.c 

,我得到的輸出從:

diff: -0.0000009537 

我知道擴展精度算術的問題,因此mfpmath=sse。查看彙編代碼,串行添加確實通過addss完成,最後用subss進行減法。

在這一點上,我很難解釋這種差異來自哪裏。如果有人能夠說明這種情況,我會非常感激。

如果它有什麼區別,我使用的是GCC 4.3.4。 (編輯:在AMD Opteron 2218 + Gentoo Linux上)

回答

1

FWIW gcc 4.2和Intel ICC 11.1給出完全相同的結果。我懷疑這只是由於執行添加的順序不同而導致累計舍入錯誤的差異。

+2

看起來你是對的。將總和改爲'(d [0] + d [2])+(d [1] + d [3])'將差值減小到零。 – 2011-05-02 17:05:55