牛乳を飲むために、牛小屋を修理しています。
singlefs の検証システムでは GPU による照合が必要です。以前は各 agent がそれぞれスクリプトを呼び出していましたが、やはり混乱していて、リソースの利用率も高くありませんでした。
最近、関連コードをリファクタリングしてタスク管理サービスを作りました。メモリ管理、シャーディング、複数マシンの協調が、以前よりずっとスムーズになりました。
うん、予想どおり予想外のことが起きました。GPU が落ちました……
Xid 62 で始まり、Xid 154 で終わる。カーネルログでは GSP が「PMU has halted」を報告し、ウォッチドッグの位置は partition 4#0、task 3。しかもコマンドで復旧できず、nvidia-smi --gpu-reset -i 0 は 2 回とも「Not Supported」が返ってきました。
最初は気にしていませんでしたが、1 日に 5 回落ちました。これがタスク管理サービスにも巻き添えの被害を出しました。タスクサービスは場を片付けるときにマシン上の全カードを検査するので、1 枚でも壊れているとマシン全体が起動できません。さらにサービスは、割り当てられた正常なカードを毎回故障扱いにして、1 枚ずつ停止していきました。結果として、1 枚のカードの不具合が、マシン 1 台の停止になりました。
そこで、2 回目で警告を入れ、3 回目でエラー耐性を入れ、4 回目でタスクの再割り当てを入れ、5 回目で、これはちょっと笑えなくなってきました……
調べてみると、原因の候補は 3 つ:
- 電源の問題
- ファームウェアの問題
- GSP スケジューリングの問題
1 電源に問題があるはずはありません。再起動すれば GPU は復旧し、長時間タスクを実行できるからです。
2 と 3 は実は同じことです。GSP ファームウェアはドライバと一緒に配布され、PMU の停止もファームウェア側が報告しています。ドライバを替えても直らないというのは、「ファームウェアではない」という意味ではなく、どのバージョンでもまだ直っていないという意味です。2026 年 8 月 19 日の先輩の記事を読んで、なるほどと思いました。GPU が極低消費電力(P8 状態)から高消費電力(P0 状態)へ頻繁に切り替わるとき、PMU のステートマシンが固まって Xid 62 になる。Blackwell アーキテクチャの GSP ファームウェアのスケジューリングのデッドロックらしい、と。
そこで、毎秒のテレメトリ(P 状態、周波数、消費電力)を、テストが打つ GPU_LIFECYCLE の時刻とカーネルの正確な時刻に突き合わせました。カードが P8 で約 13 秒アイドルしたあと、次のテストがカード上にリソースを作る 94 ミリ秒の間に Xid 62 が出ていて、実際に処理を投げるより 2 ミリ秒も早かったのです。
周波数の下限を 800 MHz 以上に固定すると、10 分間同じテストを流してもエラーは出ませんでした。固定コマンドは nvidia-smi -i <bus id> -lgc 800,3105 で、systemd ユニット nvidia-5080-min-clock にして起動時に自動で走らせています。カードをリセットすると固定は外れるので、再実行が必要です。
マシンを再起動しなくても、アンバインドして再マウントすればリセットできます。下の 0000:01:00.0 は私のマシンのバス番号なので、まず lspci | grep -i nvidia で自分の番号を確認してください。コマンドは以下のとおり:
d=/sys/bus/pci/devices/0000:01:00.0
# 1. 先に現場を残す:AER ステータスレジスタ(リセットで消える)
lspci -s 01:00.0 -vv | grep -iE 'UESta|CESta|DevSta|LnkSta'
# 2. カードを完全に解放する
fuser -v /dev/nvidia0
systemctl stop nvidia-persistenced
# 3. オーディオ機能と GPU 機能をアンバインド
echo 0000:01:00.1 > /sys/bus/pci/drivers/snd_hda_intel/unbind
echo 0000:01:00.0 > /sys/bus/pci/drivers/nvidia/unbind
# 4. PCI レベルのリセット(取り外して再スキャンするだけでこれをしないと、GSP が起動しない:「unexpected WPR2 already up」)
echo 1 > $d/reset
# 5. 両方の機能を取り外して再スキャンし、ドライバにカードを認識し直させる
echo 1 > /sys/bus/pci/devices/0000:01:00.1/remove
echo 1 > $d/remove
sleep 2
echo 1 > /sys/bus/pci/rescan
# 6. persistenced を起動し直し、周波数を再固定(リセットで固定が外れる)
systemctl start nvidia-persistenced
systemctl restart nvidia-5080-min-clock
# 7. 確認:復旧アクションが None、3 枚のカード番号が元どおり、5080 がアイドルで P8 にいない、カーネルに新しい RmInitAdapter 失敗がない
nvidia-smi -i 00000000:01:00.0 -q | grep -i 'recovery action'
nvidia-smi --query-gpu=index,name,pci.bus_id,pstate,clocks.sm --format=csv,noheader
journalctl -k --since '-2min' | grep -E 'RmInitAdapter|bad state'
私は牛小屋の上で何をしているんだろう?牛乳は?