我想正常化一個4D矢量。SSE歸一化慢於簡單近似?
我的第一個嘗試是使用SSE內在函數 - 這爲我的向量算法提供了2倍的速度提升。 這裏是基本的代碼:(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));
我檢查拆卸和它看起來像我多麼期望。我在那裏看不到什麼大問題。
不管怎麼說,然後我嘗試用近似:(我得到這個從谷歌)
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);
而且現在的修改版本(無警告)的運行速度!它的運行速度幾乎是SSE版本運行速度的60%(但結果相同)!爲什麼是這樣?
所以在這裏是問題(S):
- 是我SSE implentation是否正確?
- SSE真的比普通的fpu操作慢嗎?
- 爲什麼地獄是第三代碼慢得多?
這將有助於知道你在使用什麼樣的CPU。例如。舊的x86 CPU(Core 2之前)的SSE功能很差。 – 2011-02-01 19:17:41
我在英特爾奔騰雙核 – Pubby 2011-02-01 19:27:16