以前Go言語で囲碁実装をした話を書いた。
ちょっと思い立って改造してみることにした。
普通に強くするには機械学習かドメイン知識の導入が早い。個人的にはGo言語で実装した所以みたいなところで,王道を行かずパワープレイでってことを考えて多スレッド化することにした。
簡単にはMCTSの並行処理化というところだ。
この辺の再検証のツール(の布石)になるのかもしれない。
元ネタがシングルスレッド実装な上,多くの変数がグローバル定義されている。
これをスレッド毎に実装し直し,同期をとるタイミングでスレッド間処理をおこなう。
そんなに難しいことではないが探索木構造など共有する部分があって更新には気をつかう。
簡単にはロックしてしまえばいいんだが,雑にやるとパフォーマンスに影響があるので可能な限りエレガントにやりたい。
ということで勝ち数などのインクリメントにはsync/atomicを使うことにした。
・・・
int32とint64しかあらへんやん。
黙ってたらintにするくせに
ということで,変数の型を変えることに。
Go言語はこれらの型を自動変換してくれないので全て宣言しなくてはならない。
ちょいしんどい。
今後最初から組むことがあればカウンタの類は全部int64にしようと誓う。
ところで,goroutineを使うときには-raceオプションを一度は試すべきとの話がある。
あー,当然のように木構造の更新でお祭り状態ですわ。
競合じゃなく皆で木構造を拡大していくんで仕方ないですね。
で,極稀に飛びます。
このまま放置できないのでデバッグ沼に・・・
その後,探索数と勝ち数と勝率の更新は同時でないとダメなことに気付いてatomicが全部無駄になるなど
Go言語でも実装難易度がさほど下がってない気がした。