短期目標
当面の方針は「ひたすら高速化する」ですが、今まで書いてなかった事も含めてまとめときます。
まず、やる予定の事。括弧内は速度向上率の目標値。
- マルチスレッド化 (x6)
- 評価関数の再実装 (x3)
- 二駒の相対位置関係のチューニング (x1.2)
- ログ出力まわりの整理 (x1.05も行かないかも)
- ルートノードでの枝刈り(x4位は行って欲しい)
- 探索ノード数の削減 (x1.5)
以下、項目ごとに。
マルチスレッド化
方策がソフトマックスなので「対局中の局面から深さ1の全ノードの正確な評価値を計算する」という処理があります。
で、各ノードの評価値の計算(探索)は完全に独立しているので、この部分で並列化の予定。
CPUがCore i7なので、4コア8スレッドで速度向上が6倍あたりが限界だと予測。ただ、これは(計算結果に影響を与えない)純粋な高速化なので、ここで出来るだけ速度を稼ぐ。
評価関数の再実装
現在はstd::mapを使っていて遅いので、局面評価時はmapを使わない様に修正。
パラメータ修正時はmapが必要だけど、そっちはボトルネックにならないので無視。
マルチスレッド化と同じく、純粋な高速化。ここでも速度を稼ぐ。
二駒の相対位置関係のチューニング
相対位置関係は先後や左右を反転した関係が複数あって、これを特定の一つの関係に変換してから局面評価に使ってます。
で、この変換処理はif文が入れ子になった、いかにも遅そうなコードなので、ここをチューニングします。
変換処理自体は単純に表を見るだけでも実現可能なので、使用するメモリの量さえ足りるなら表引きで実装予定。
純粋な高速化だけど、大幅な速度向上は多分無理。優先度低い。
ログ出力まわりの整理
ログ出力用の関数があって、出力するメッセージのログレベルを設定ファイルの閾値と比較して、出力の有無を決めている部分があります。
が、マクロを使えば出力しない部分はザクッと消せるので、そうしようかと検討中。
ひたすら置換するだけで実装コストは低いけど、その分リターンも低い。
ルートノードでの枝刈り
上で書いた「対局中の局面から深さ1の全ノードの正確な評価値を計算する」という処理に手を加えようかと検討中。
全合法手をウィンドウ[-∞,+∞]で探索すると無駄なので、[仮の最善手の評価値 - マージン,+∞]にして高速化出来ないかと考えてます。
ソフトマックスだと評価値が高いほど高確率で選択しますが、私が今使ってる温度の設定だと、評価値が0.2低いと選択確率が480万分の1になるので、マージン0.2にしとけば実用上問題ない範囲で枝刈り可能…なハズ。
これは純粋な高速化ではないので、実際にやってみながら出たとこ勝負で何とかします。
…マージン0.15だと10万分の1・・・そこまでマージン削ると危険かなぁ・・・・・・
// 以下、追記
探索ノード数の削減
基本を忘れてましたが、探索ルーチンが今のもので良いのかも検討しないといけません。
とりあえずは序盤〜終盤でのノード数やmpn*1の変化を調べて、後はその結果次第ですね。
ただ、実際のところムーブオーダリングの改善ぐらいしか出来る事は無いので、やったとしてもあまり成果は出ないかも。