Нормализация SSE медленнее, чем простое приближение?

Я пытаюсь нормализовать 4-мерный вектор.

Моим первым подходом было использовать встроенные функции SSE - то, что обеспечивало двукратное увеличение скорости моей векторной арифметике. Вот базовый код: (v.v4 - вход) (с использованием GCC) (все это встроено)

//find squares
v4sf s = __builtin_ia32_mulps(v.v4, v.v4);
//set t to square
v4sf t = s;
//add the 4 squares together
s   = __builtin_ia32_shufps(s, s, 0x1B);
t      = __builtin_ia32_addps(t, s);
s   = __builtin_ia32_shufps(s, s, 0x4e);
t      = __builtin_ia32_addps(t, s);
s   = __builtin_ia32_shufps(s, s, 0x1B);
t      = __builtin_ia32_addps(t, s);
//find 1/sqrt of t
t      = __builtin_ia32_rsqrtps(t);
//multiply to get normal
return Vec4(__builtin_ia32_mulps(v.v4, t));

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

В любом случае, потом я попробовал использовать приближение: (я получил это из Google)

float x = (v.w*v.w) + (v.x*v.x) + (v.y*v.y) + (v.z*v.z);
float xhalf = 0.5f*x;
int i = *(int*)&x; // get bits for floating value
i = 0x5f3759df - (i>>1); // give initial guess y0
x = *(float*)&i; // convert bits back to float
x *= 1.5f - xhalf*x*x; // newton step, repeating this step
// increases accuracy
//x *= 1.5f - xhalf*x*x;
return Vec4(v.w*x, v.x*x, v.y*x, v.z*x);

Он работает немного быстрее, чем версия SSE! (примерно на 5-10% быстрее) Результаты также очень точны - я бы сказал, что при определении длины до 0,001! Но ... GCC дает мне это неубедительное правило строгого псевдонима из-за каламбура типа.

Итак, я изменяю его:

union {
    float fa;
    int ia;
};
fa = (v.w*v.w) + (v.x*v.x) + (v.y*v.y) + (v.z*v.z);
float faHalf = 0.5f*fa;
ia = 0x5f3759df - (ia>>1);
fa *= 1.5f - faHalf*fa*fa;
//fa *= 1.5f - faHalf*fa*fa;
return Vec4(v.w*fa, v.x*fa, v.y*fa, v.z*fa);

И теперь модифицированная версия (без предупреждений) работает медленнее !! Он работает почти на 60% быстрее, чем версия SSE (но тот же результат)! Почему это?

Итак, вот вопрос (ы):

  1. Правильная ли моя реализация SSE?
  2. Действительно ли SSE медленнее, чем обычные операции с FPU?
  3. Почему, черт возьми, третий код намного медленнее?
6
задан Pubby 1 February 2011 в 19:57
поделиться