TadaoYamaokaの日記

山岡忠夫Homeで公開しているプログラムの開発ネタを中心に書いていきます。

将棋AIの進捗 その47(Linuxのマルチスレッド排他処理)

昨日の記事で、dlshogiのゲーム木の管理をロックレス方式に見直しを行った。

Windowsでは、ノード単位の排他制御をmutexを用いずに、atomic_flag (TAS機能)で実現することで10%NPSが向上したが、Linuxで測定すると800NPSくらいしかでないという悲惨な結果になった。

原因

Linuxのスレッドは、Windowsのスレッドとは異なり、プロセスの一種にすぎない
そのため、コンテキストスイッチのコストが高い。

atomic_flagでビジー待機を行った場合、スレッドの切り替えが頻発し、そのたびにコンテキストスイッチが起きる。
そのことが、Linuxでの性能低下を招いたと思われる。

ジー待機の間にstd::this_thread::yield()を追加してみたが、結果は同じであった。

対策

atomic_flagで排他制御を実装した方が高速になると考えていたが、素直にmutexを使うことにした。
ノード作成のたびにmutex作成のコストが発生するため、オーバーヘッドがあると予想していたが、Windowsでの性能低下は0.5%程度と誤差の範囲であった。

Linuxでは、mutexで実装することで、ノード再利用の方式見直し前と比較して、Tesla V100 8GPU、GPUあたり3スレッドで、floodgateからサンプリングしたした局面での平均NPSは、

変更前 66236.7
変更後 159334.9

となり、約2.4倍になった。

mutexで排他制御を行うことでコンテキストスイッチが抑えられて高速になっている。

mutexは、OSに合わせて最適に実装されているので、独自実装するより素直に標準で用意されいてるものを使った方がよかった。

補足

ノード再利用の待ちがなくなったことで、潜在バグが見つかった。
dlshogiでは、詰み探索をモンテカルロ木探索と並列で動かしているが、詰み探索スレッドの開始のタイミングで局面のコピーを行ってから探索していたが、ノード再利用が速くなったことでコピー前に局面が変更されることでまれに不正な結果を返すことが発生するようになった。
スレッド開始前に局面をコピーするように修正を行った。

ノード再利用の変更前にも発生する可能性はあるので、先日公開したバイナリも修正版に差し替えた。
Release 世界コンピュータ将棋オンライン大会バージョン · TadaoYamaoka/DeepLearningShogi · GitHub

※2020/5/8 追記 修正にバグがあったので再度差し替えた

まとめ

排他制御をatomic_flagを使ってビジー待機で実装すると、Linuxでは性能がでない。
素直にmutexを使った方がよいことがわかった。
修正することで、Linuxでもノード再利用の方式見直しにより高速化できた。

NPS向上により強くなっているか、floodgateでテストする予定。

2020/5/8 追記

途中で投了するバグがあるので見直し中
→マルチスレッド関連の考慮漏れがあったので修正した。