調べても出てこなかったので備忘録として書いておきます.稚拙な文章をダラダラと記述する形式です.
問題が発生してググると,有能な人がブログ記事に解決策などを書いておいてくれることで助かった経験が何度もあったので,真似してみるとします.
問題の内容
- NVIDIA A100を4台搭載したGPUサーバーで,4つともGPUを使うとnvidia-smiしたときのGPU-Utilが50%くらいまでしか行かない.
- 2つまでなら100%近くまで行くが,3つだと60-70%くらい.
走らせていたプログラムはCUDAで開発した自作のシミュレーションコードで,IO以外ほぼGPU駆動なので100%近くになるべきコード.
OpenMPIを使っていて複数GPU対応コードだが,問題発生時にはmpirun -n 1などの設定でシングルGPU実行.
簡単なサーバー構成
ちなみに,問題に直面する前はNUMAノードのことをよくわかっていませんでした.
特定に至るまで
- topコマンドでプロセスのCPU使用率を見ると50%までしか行っていないのでCPU起因の問題の可能性を疑う
- ググっても情報が出ないのでとりあえずnvidia-smiコマンドをオプションありでいろいろ叩く
- nvidia-smi topo --matrixで各GPUに対するCPU Affinityを見ると論理コアの割当(GPU0,1は0-19,40-59でGPU2,3は20-39,60-79)が見えたので,試しにtopと打ったあとに1と入力して論理コアあたりの負荷を見てみる
- なぜか0と40番ばかり使われていてほかが全然使われていない状況を知る
- 論理コアの割当がなんかうまくいっていない?と原因を推定
- ググるとtaskset -pc <PID>でプロセスが使う論理コア番号がわかるらしかったので,該当のGPUプログラムのPIDをtopなどで見て打ってみると論理コア番号0,40しか使わない設定で動いていることが判明
- 試しに手持ちのシンプルなCUDAコードを走らせるとこちらは0-79を使う設定になっている
- MPIが組み合わさっているとaffinityが適切にならない?と思い調べたがそれっぽい情報見つからず
- とりあえず論理コアのaffinityを指定するコマンドで暫定的に解決を試みる
- mpirun -n 1 numactl --cpunodebind=0 ./a.out みたいな書き方でやると,0番目のCPUのaffinityが多分強制的に適用されて,今回の設定の場合は0-19,40-59が割り当てられた!
- 私の環境ではGPU2,3の場合はmpirun -n 1 numactl --cpunodebind=1 ./a.out にマニュアルでしないといけないのでスクリプトでこの辺自動化したいところ.
解決策抜粋
taskset -pc <PID>
でプロセスの論理コアaffinityを見て,それが適切でない場合.他のGPUも同じ論理コアを集中して使用しているために性能が落ちている.この場合
numactl --cpunodebind=0 ./a.out
のようにaffinityを指定すれば暫定的な解決にはなる.--cpunodebind=1の部分はnvidia-smi topo --matrixを見て自分が使っているGPU番号に本来割り当てられているべきaffinityに対応するCPU番号を設定してください.