日別アーカイブ: 2009年8月8日

Direct3D Matrix の並びと SSE 命令 (2)

先日の SSE 命令の実行速度を試してみました。
あまり厳密なものではなくて、掲載したコード 3種類をそのままループで回しただけです。

● Core2 Duo P8600 2.4GHz Windows7 x86

x86  SSE1       17581 (msec)  mulps+addps
x86  SSE3       20623         haddps
x86  SSE4.1     17799         dpps

● Core i7 940 2.93GHz Windows7 RC x64

x86  SSE1       14320         mulps+addps
x86  SSE3       11716         haddps
x86  SSE4.1     13682         dpps

x64  SSE1       17269         mulps+addps
x64  SSE3       11076         haddps
x64  SSE4.1     13681         dpps

単位は時間で値が小さい方が高速です。

Core2 実行時、SSE3 hadd で遅くなってしまい少々焦りました。
昨日これで良いって書いたばかりなのに。結局元のコードの方が速いという結果に。
Core i7 の場合は正反対で hadd が最速になっています。

おかしなことに x64 のみ SSE1 で極端に速度が落ちています。
実際に x64+SSE1 の展開されたコードを見てみると、x64 で増えたレジスタを最大限
使おうとしてループの先頭で全部レジスタにロードしていました。
その分転送などの命令が他のケースよりも増えています。

このテストは局所的な小さいループかつ、使用したデータもストリーム入出力ではなく
同じ領域へのたたみ込みでした。
それゆえすべてのデータがキャッシュに乗った状態だと考えられます。
レジスタ間の転送命令が増えるよりもおそらくキャッシュに乗ったメモリから
読み直した方が速いのでしょう。

実際に SSE 命令が使われるケースだとストリーム処理が多いため、必ずしも
このような結果にはならないと思われます。

haddps , dpps の実行性能は CPU によって逆転することがわかりました。
この両者は比較的似たようなコードに展開されています。
ループ内の命令数も同数でした。
プロセッサによって異なるため、やはり指針としては命令数を減らすことを考えて
書くのが良さそうです。

関数は intrinsics 命令で記述しためコンパイラは inline 展開しており、
複数の関数に渡って並べ替えなどの最適化が行われています。
intrinsic 命令がどのように展開されるかだけ把握しておけば asm を使わない方が
良いかもしれません。x64 だと使えないし。
_mm_setr_ps とかは結構命令数食います。

関連エントリ
Direct3D Matrix の並びと SSE 命令
Intel AVX その3 命令
D3D10 row_major column_major
SSE についてのメモ(2) SSE4など