CPU自己対局ループの無駄なパディングを削り、実行時間を16.6%短縮した
自己対局(self-play)、学習(training)、モデル評価(arena)をすべてCPU環境で回す1世代(generation)の実行サイクルでは、処理時間の大半をONNX Runtimeによる推論が占めていた。そこで探索アルゴリズムや学習レシピには手を加えず、ニューラルネットワークに渡すデータ行数とパディングの無駄を徹底的に削る方針で最適化を進めた。
個別のステージを対象としたマイクロベンチマークでは25.2%の短縮が確認されたものの、一連のパイプライン全体を通しで測定したところ、最終的な短縮幅は16.6%にとどまった。本稿では実態に即した指標として、後者の数値を採用値としている。
何を変えたか
| 変更内容 | 測定結果 |
|---|---|
| 論理CPUではなく物理コアごとにworkerを配置 | 16 workers 約5,400 rows/s → 8 workers 約7,600 rows/s |
| 同一の公開局面(public state)に対する推論結果をメモ化 | evaluator rows: self-play -8.1%、arena -2.8% |
| 合法手の候補数に応じてバッチを適切に分割 | padded/actual比: self-play 1.68→1.08、arena 2.22→1.11 |
| opset 20のGELUを使用 | 0.937 ms/row → 0.899 ms/row |
| 存在するentity/candidateの行のみを計算 | 約8,100 rows/s → 約11,800 rows/s |
特に大きな効果を上げたのは、やみくもにワーカー数を増やすことではなく、不要な行(row)や余計なパディングの削減だった。
実ループでは16.6%短縮
同一のGCE c3d-standard-16 Spot VM環境において、自己対局256局、学習512 updates、arena評価800 pairsからなる1世代をエンドツーエンドで比較した。
| stage | baseline | treatment | change |
|---|---|---|---|
| self-play | 196.0 s | 164.4 s | -16.1% |
| training | 375.7 s | 325.1 s | -13.5% |
| arena | 1,285.5 s | 1,053.7 s | -18.0% |
| generation total | 1,866.3 s | 1,555.6 s | -16.6% |
baselineではarenaが世代全体の処理時間の約69%を占めていたため、自己対局や学習だけを高速化してもエンドツーエンドでの改善幅には限界があった。
高速化したが採用を見送った手法
| 試したもの | 結果 | 採用しなかった理由 |
|---|---|---|
| dynamic INT8 | 8,139 → 13,286 rows/s | policy top-1一致率が94.8%に低下し、評価器の挙動自体が変わる |
| bf16 CPU training | 1 updateで約19%高速化 | 学習レシピの前提が変わってしまう |
| arena concurrency 32→128 | 約19%低下 | ワーキングセットの増大によるキャッシュ効率悪化 |
単体のマイクロベンチマークだけでなく、実際に運用するワークフロー全体で検証し直したことで、確実に享受できる実行時間短縮の効果を16.6%と見極めることができた。同じCPU予算のなかで実験のイテレーション回数を増やせることが、今回の最適化の最大の成果である。
この記事は、実装・実験記録をもとに、本文の大部分をLLMが執筆し、筆者が内容を確認・編集しています。