はじめての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倍速いはずです。使えったら使え、です。


つづく