Stockfish DD – bitcount.h

今回はStockfishのbitcount.hです。これは、2進数的に見て1になっているbitの数を数えるというものです。いわゆるpopcountですね。SSE4.1以降であればx86/x64ではpopcnt命令が使えますので簡単なのですが、そうではない環境ではビット演算のテクニックを用いて求めることになります。

popcountは、王に利きのある敵駒のbitboardを得たときにpopcountしてそれが2以上であれば両王手なので次の合法手としては王が逃げる指し手のみを生成するときに使えます。Stockfishのmore_than_one( )という関数がそれです。というか、この使い道以外は将棋ではほとんどないような…。

そう言えば、私は棋譜からの学習のときに評価因子に正規分布っぽい乱数を加算するのに、popcount(rand() & 7) とかやってますが(二項分布≒正規分布なので)…まあ、こんなところはたいした問題ではないですね。

 


Stockfish DD – bitcount.h” への4件のコメント

    • はい、そうですね。両王手のみだったら、最下位ビットを消すビット演算のテクニック(x & (x-1))が使えますね。将棋盤面は128bitでないと収まらないので、これに対してこの処理を行なうのは結構嫌ですね。x-1のところが綺麗に書けないので…。

      なのはの場合、GPSっぽくどこから利きがあるか各升ごとに持っていたと思うので、ある升への利きは32bit変数に収まるので問題ないということですね。GPS風に持つと盤面のupdateするときのコストが高いのが私は嫌なんですが、利きを持っていると判定が速く済む部分もあるので全体的には相殺するんでしょう。もしかすると速かったり?うーん。比較実験してみたい気分になってきたぞ…。

      • 両王手に限って言えば,王手している駒のbitboardのそれぞれの変数の論理和を取ってやることで速くできないでしょうか?

        両王手のときには玉を攻撃している二つの駒が異なる筋にいることが保障されているので,論理和を取っても立っているbitの数は変わらないと思います. それで本当に速くなるのかはよくわかりませんが……

        • 王手している駒のbitboardのそれぞれの変数の論理和を取って

          取ってます。ある地点sqに対して利いている手番turn側の駒のbitboardを得る関数
          Bitboard attackers_to(Square sq,Turn turn) const;
          みたいな関数がありまして、これを用いているので実際のコードとしては、
          if ( more_than_one( attackers_to(sq,~us))) { // 両王手
          のようなコードになっちょります。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です