はじめてのSSE その2
それではSSE命令の使い方を説明していきましょう。
SSE2命令だけを使うときは、emmintrin.hをincludeします。
SSE2/SSE4の命令を使うときは、smmintrin.hをincludeします。
つまり、以下のようになります。
#if defined(HAVE_SSE2) || defined(HAVE_SSE4) #if defined(HAVE_SSE4) // SSE4 # include <smmintrin.h> #else // SSE4なしでSSE2 # include <emmintrin.h> #endif #endif
Bonanzaのbitop.hが参考になります。
これでSSE2/4の命令が使えるようになりました。
いまどきのCPU(Core i7以降)ならばSSE 4の命令が使えます。
正確には、このあと使いたいのはSSE4ではなくSSE4.2の命令でして、コンピューター将棋向けCPUとしてコストパフォーマンスに優れていると噂のPhenom II X6では、SSE 4a(←意味がよくわからないのですが、4.2じゃないんでしょうね)しか対応していなくて、これから使おうとしている命令は使えません。Phenom II X6ならSSE2までの命令で我慢しましょう。
それではSSE2の命令を使ってみましょう。
まず128bitのBitboardを用意します。32bit☓3のBitboardを使っているなら、SSE2/4を使うときのみ末尾に32bitをひとつpaddingして128bitにしてください。
(このあと引用しているソースは、Bonanzaからではなく私の書いたソースからの引用です。)
struct Bitboard { union { u64 p[2]; #if defined(HAVE_SSE2) || defined(HAVE_SSE4) __m128i m; #endif // SSE 2/4で使うので。 }; };
こうですね。これに対して、次のマクロを使ってください。
// And,Or,Xor #define Bitboard_And(b,b1,b2) (b).m = _mm_and_si128( (b1).m, (b2).m ) #define Bitboard_Or(b,b1,b2) (b).m = _mm_or_si128( (b1).m, (b2).m ) #define Bitboard_Xor(b,b1,b2) (b).m = _mm_xor_si128( (b1).m, (b2).m ) // ゼロ初期化 #define Bitboard_Zero(b) (b).m = _mm_setzero_si128() // ↓のようにして使います。 // Bitboard b1,b2,b3; // Bitboard_And(b1,b2,b3);
and/or/xor/ゼロ初期化はこれで一命令で出来るようになりました。速いです。x64環境でもこちらのほうが1.5倍〜2倍ぐらい速いです。x86環境なら言うまでもないでしょう。3〜4倍速いはずです。使えったら使え、です。
つづく