SSE не соответствует добавлению серийного числа - PullRequest
2 голосов
/ 02 мая 2011

Вот тестовая программа, которая приносит мне горе:

#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 Ответ

1 голос
/ 02 мая 2011

FWIW и gcc 4.2, и Intel ICC 11.1 дают абсолютно одинаковый результат. Я подозреваю, что это просто разница в накопленных ошибках округления из-за разного порядка, в котором выполняются добавления.

...