Переключение знака на упакованных поплавках SSE - PullRequest
13 голосов
/ 29 июля 2010

Я ищу наиболее эффективный способ перевернуть знак на всех четырех поплавках, упакованных в регистр SSE.

Я не нашел ничего подобного в руководстве разработчика ПО для архитектуры Intel. Ниже приведены вещи, которые я уже пробовал.

Для каждого случая я перебирал код 10 миллиардов раз и получал указание времени стены. Я пытаюсь, по крайней мере, сопоставить 4 секунды, это занимает мой не SIMD подход, который использует только унарный оператор минус.


[48 секунд]
_mm_sub_ps( _mm_setzero_ps(), vec );


[32 с]
_mm_mul_ps( _mm_set1_ps( -1.0f ), vec );


[9 секунд]

union NegativeMask {
    int   intRep;
    float fltRep;
} negMask;
negMask.intRep = 0x80000000;

_mm_xor_ps( _mm_set1_ps( negMask.fltRep ), vec );


Компилятор - gcc 4.2 с -O3. Процессор Intel Core 2 Duo.

Ответы [ 3 ]

22 голосов
/ 20 августа 2010

Этот союз на самом деле не нужен, лучший из всех миров (удобочитаемость, скорость и портативность):

_mm_xor_ps(vec, _mm_set1_ps(-0.f))
4 голосов
/ 29 июля 2010

Просто чтобы завершить свой собственный ответ документацией gcc об этих встроенных векторах:

The types defined in this manner can be used with a subset of normal C
operations.  Currently, GCC will allow using the following operators on
these types: `+, -, *, /, unary minus, ^, |, &, ~'.

Вероятно, хорошей идеей будет всегда придерживаться этого, когда это возможно. С очень высокой вероятностью gcc всегда предоставит наиболее эффективный код для этого SSE.

Для параметров компилятора добавьте что-то более специфичное для вашей архитектуры, что-то вроде -march=native в большинстве случаев подойдет.

2 голосов
/ 29 июля 2010

Жизненный урок о кодировании до 3 часов ночи .....

Я никогда не пытался просто использовать унарный минус на моем упакованном векторе. Это на самом деле компилируется и имеет ту же производительность, что и подход без SIMD.

...