POV-Rayでは、倍精度浮動小数点演算を多用しています。単精度では精度が足りないらしく、 単精度浮動小数点演算しか実行できないSSEや3DNow!を使っても高速化することはできませんでした。 コンパイラに頼るだけでは、高速化にも限界があります。 ところが、Pentium 4に実装されたSSE2からは倍精度浮動小数点演算を実行できるので、 POV-Rayを高速化できるのではないかと考え、インラインアセンブラの勉強がてらに挑戦してみることにしました。 AMDもK8(Hammer)プロセッサからSSE2をサポートすることを表明しているので、今後SSE2が標準となっていくのは間違いありません。
・SSE2の倍精度浮動小数点演算命令の概要
例えば、次のようなC言語のプログラムを考えてみます。
double input1[2],input2[2],output[2]; output[0] = input1[0] + input2[0]; output[1] = input1[1] + input2[1];コンパイラは、単純に2回の浮動小数点加算命令を使って処理させようとするでしょう。 SSE2命令を用いると、この二つの計算を一度に行うことができます。 次のプログラムは、上のプログラムと同じ結果が得られます。
double input1[2],input2[2],output[2];
_asm
{
movupd xmm0, input1 ;xmm0={input1[0],input1[1]}
movupd xmm1, input2 ;xmm1={input2[0],input2[1]}
addpd xmm0, xmm1 ;xmm0={input1[0]+input2[0],input1[1]+input2[1]}
movupd output, xmm0 ;
}
同様にして、減算はsubpd、乗算はmulpd、除算はdivpdという命令で実行できます。
平方根を求めるsqrtpdという命令もあります。SSEにはあった逆数を求める命令は、倍精度では実装されなかったようです。
アドレスを16バイトの境界に合わせると、movupdをmovapdというより高速なロード/ストア命令に置き換えることができます。
その他、論理演算を行うandpd,orpd,xorpdや、レジスタ内のデータを入れ替えるshufpdなどの命令が実装されています。
・サイン,コサインの計算
POV-Rayのソースには三角関数の計算が数多く出てきますが、残念ながらSSE2はサイン,コサインの値を計算することができません。
仕方がないので、x87命令のfsincosという命令を使ってサインとコサインの値を同時に求めます。次のようなプログラムで
変数angleのサイン,コサインの値を同時に計算し、変数cosx,sinxに保存できます。fsin,fcos命令で別々に計算するよりも高速です。
double angle,cosx,sinx;
_asm
{
fld angle ;
fsincos ;
fstp cosx ;
fstp sinx ;
}
・Matrices.cの最適化(作成中)・ダウンロード(作成中:POV-Rayのバイナリやソースの配布条件などを調べているところです)
もっと良い方法がありましたらこちらまで:matsui@katto.comm.waseda.ac.jp
Last update:11/10/2001