« 炎エフェクトを使えるレベルに | メイン | 炎を入れてあれこれ »

2008年03月03日

x86 SIMD Technique:: SSE からの整数値の取り出し

    

_mm_cvtt_ss2si を使えば、切り捨てを使用して 32 ビット整数を取得出来るが、取り出せるのは最下位のみ。
SSE2 があれば、4つ取り出せるが、SSE では出来ない。
そのためシャッフルを使うが、これは以下のようにぐるぐる回して取り出したほうが良い様子。

i = _mm_cvtt_ss2si( a );
a = _mm_shuffle_ps( a, a, _MM_SHUFFLE( 0, 3, 2, 1 ) );
...
i = _mm_cvtt_ss2si( a );
a = _mm_shuffle_ps( a, a, _MM_SHUFFLE( 0, 3, 2, 1 ) );
...
i = _mm_cvtt_ss2si( a );
a = _mm_shuffle_ps( a, a, _MM_SHUFFLE( 0, 3, 2, 1 ) );
...
i = _mm_cvtt_ss2si( a );

これを以下のようにすると見た目すっきりするけど、少し遅いみたい。

i = _mm_cvtt_ss2si( a );
...
i = _mm_cvtt_ss2si( _mm_shuffle_ps( a, a, _MM_SHUFFLE( 1, 1, 1, 1 ) ) );
...
i = _mm_cvtt_ss2si( _mm_shuffle_ps( a, a, _MM_SHUFFLE( 2, 2, 2, 2 ) ) );
...
i = _mm_cvtt_ss2si( _mm_shuffle_ps( a, a, _MM_SHUFFLE( 3, 3, 3, 3 ) ) );

たぶん、下の方法だと余計なレジスタコピーが発生するからだと思う。
他でも xmm レジスタを何個か使っているようなソースコードの場合、計測して違いが出るぐらいの速度差になった。

補足:
_mm_cvtt_ps2pi を 使えば、__m64 に2個の 32 ビット整数を一度に取り出せる。
ただ、__m64 を使うと、その後浮動小数点を用いた計算をする場合、_mm_empty をコールしなければならない。
SSE を使っていると、近くで浮動小数点を使っていることが多いと思うが、その時は _mm_empty を忘れずに呼ばないと計算結果がおかしくなる。
_mm_cvtt_ps2pi で値を取り出したあと、MMX である程度処理するのであれば、2個同時に取り出した方が速いかもしれない。
1個ずつ取り出すか、2個同時に取り出すかは、その後の処理次第で、どちらが速いかを計測してから決めた方が良い。
MMX の2個同時程度であれば、MMXを使わずに普通に書いたほうが速い場合も多い。



投稿者 Takenori : 2008年03月03日 14:58




comments powered by Disqus
Total : Today : Yesterday : なかのひと