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%です(ただし同じ結果)!どうしてこれなの?
だからここに質問(複数可)されています
- は正しい私のSSEのimplentationですか?
- SSEは通常のfpu操作よりも実際に遅いですか?
- なぜ3番目のコードが非常に遅いのですか?
これは、使用しているCPUを知るのに役立ちます。例えば。古いx86 CPU(pre Core 2)は非常に劣悪なSSE機能を持っていました。 –
私はIntel Pentium Dual-Coreを使用しています – Pubby
Duplicate of http://stackoverflow.com/questions/1528727/why-is-sse-scalar-sqrtx-slower-than-rsqrtx-x? – celion