ボナッセ・コーポレーション
ボナ自体の改良には手を出さないつもりでいたんですが、大会が近づいてくると日和ってしまい「手軽にできることならやっとこうか」などと思いましてここしばらくボナの改良ネタを探していました。でぱっと思いついたのがbitboardのSSE化。32bitの配列というのはいかにもムダに思えます。そこでSSE化にトライしてみました。64bit化という考えもあるでしょうが、どうせなら128bitで1サイクルでやりたくなりますよね。
コン将関係者には周知のことかと思いますが蛇足ながら解説しときますと、SSE命令セットとはShogi SIMD Extensionsの略。Intel社がそのオレゴンチームとイスラエルチームの総力を結集して、コンピュータ将棋の高速化のために特別に開発した拡張命令セットです。(<嘘をつくな、嘘を)ちなみに都市伝説によるとあのGPS将棋もSSEを駆使していると言われています。
すべてのルーチンをSSE化したわけではなく、プロファイラでみて比較的実行時間が多くかつSSE化しやすそうなものをいくつか選んでSSE化しました。主にattack系と[un]makemove系。これらだけでも実行時間で約15%で、いくつかの局面で測ったところCore i7で一割弱高速化できたようです。ただしPentium 4ではほとんど速くなってなかったりもして、CPUによってYour Mileage May Varyです。
evaluateやmovegen系への適用も当然考えたんですが、このあたりは
- bitboardからFirstOneで一つ選ぶ
- そのビットに対して何かする
- Xorでそのビットを落とす
というループが多いんですが、このFirstOneにあたるのがSSEでうまい命令がないんですよね。そこで挫折したためできてません。Intelさんにはぜひxmmに対するbsr/bsf命令の実装を望みたいところです。
SSEプログラミングにはなじみのない方も多いかと思いますが、たとえばボナだと、shogi.hで
#define BBOr(bb,bb1,bb2) (bb).p[0] = (bb1).p[0] | (bb2).p[0], \
(bb).p[1] = (bb1).p[1] | (bb2).p[1], \
(bb).p[2] = (bb1).p[2] | (bb2).p[2]
とあるところへ
#define castbb(bb) (*((__m128i*)(&(bb))))
#define BBOrS(bb,bb1,bb2) bb = _mm_or_si128( castbb(bb1), castbb(bb2) )
などとしておき、*.cでは
#ifndef USE_SSE
bitboard_t bb_set_clear;
BBOr( bb_set_clear, abb_mask[from], abb_mask[to] );
#else
__m128i bb_set_clear;
BBOrS( bb_set_clear, abb_mask[from], abb_mask[to] );
#endif
という感じ。元のボナがこの辺統一的に書かれているので、こちらも作業しやすかったです。
ハマった点としては、BBContract相当はSSE4のPTESTを使ってるんですが、i7はそれでよくてもPhenomIIはSSE4がないためIllegal Instructionになってしまい、extract_epi16を6回使うはめになったりとか。あとRankは32bitに収まるためボナでは別扱いになってることが多いんですが、こっちはxmm上でやらないといかんのでset_epi32にしたりとか。_mm_set_epi32(*,*,aslide[sq].ir0)とか書けるとウマーなんですが、set_epi32の第3オペランドは即値でないとダメ、とか orz (これにはマジがっくり来た)
まあそんなこんなで作ったのをfloodgateに投入したのがbonasse(ボナッセ)です。東京は多摩センターに本部のある某教育関連企業とは全く関係ありません。進○ゼミ、とか言っても若い人には通じないのかな。マシンリソースの関係で対局数十分でないですが、いちおうレーティングはこちら:
まあ2682ははっきり言ってできすぎで、指運に恵まれたんでしょうが、元のボナよりかなり有意に強くはなってるでしょう。ちなみにこれ、1コアです。4コアだとどうなるんだろう。なおSSE以外にもいろいろいくつかいじってますんで、SSEだけでここまで強くなるわけではないです。
さて次は、これらの改造をボンクラーズに組み込むんだけど…これがなかなか一筋縄ではできなくて orz
最近のコメント