spark-training-gotchas について
DGX Spark のトレーニング運用者向けに、起動、メモリ、性能、精度の問題を調べるスキルです。よくある故障を G1~G10 に分類し、確認方法と一部の事前チェック用スクリプトを提供します。
主な機能
- 0110種類の番号付き故障項目
- 02症状・原因・確認・修正の案内
- 03一部の問題を調べる事前チェック用スクリプト
- 042台の Spark の並列化に関する助言
活用シーン
- 01CUDA のインポートエラーやセグフォルトの調査
- 02空き容量が表示される状況での OOM の調査
- 03長時間実行中のスループット低下の確認
- 042台の Spark での学習方式の選定
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ wshobson/ agents --skill spark-training-gotchasインストール後、Claude Code で/spark-training-gotchasを入力して読み込まれたか確認します。
同梱ファイルassets/preflight.shreferences/gotcha-checks.md
詳細
Spark トレーニングの落とし穴
DGX Spark の GB10 チップ(Grace Blackwell、SM121、128GB 統合メモリ、aarch64)には、起動、メモリ、熱、帯域幅、精度にわたる 10 の再発性の障害モードがあります。それぞれ G1~G10 と名前を付けて番号で確認できるようにしています。この番号付けは、これらのチェックを実行するツールにとって重要な意味を持ちます。長時間の実行の前に読んでください。6 時間目が終わってからでは遅いです。
このスキルを使うべきとき
- トレーニング実行が起動に失敗し、本当の原因を指し示していないインポートエラーやセグメンテーション違反が発生する。
nvidia-smiがまだ余裕を示しているのに、実行が OOM になる。- 順調に始まった実行の途中でスループットが低下する。
- GB10 で数時間または複数エポックにわたるジョブを実行する前。
- 2 台の Spark を接続するとき、並列化戦略を選ぶ前。
- Spark 上で実行する用途で FP8 と NVFP4 のどちらを選ぶかを決めるとき。
よくある問題のクイックリファレンス
| # | 症状 | 修正 |
|---|---|---|
| G1 | undefined symbol / セグメンテーション違反 | cu130 ホイールまたはコンテナ |
| G2 | flash-attn が誤ったバックエンドを使用 | pip ビルドをスキップ。NGC ではモンキーパッチ |
| G3 | 余裕があるのに OOM | ページキャッシュを破棄 |
| G4 | スループット低下 / 再起動 | 約 100W の持続上限を想定 |
| G5 | メモリバウンドのステップが遅い | 180~192 GB/s を見込む |
| G6 | 実行途中でキャッシュが追い出される | 一度に 1 つの GPU サーバー |
| G7 | NVFP4 が FP8 より遅い | sm_121a でない限り FP8 のまま |
| G8 | プレイブックが完全に失敗 | 上流の issue を確認 |
| G9 | インストール後に環境が壊れる | コンテナを使用 |
| G10 | 2-Spark の TP がハング | DDP/FSDP のみ、TP は決して使わない |
10 の落とし穴
G1: CUDA 12/13 の ABI 不一致
- 症状: CUDA 関数を名指しする
ImportError: undefined symbol、または最初の.cuda()呼び出しでのセグメンテーション違反。 - 原因: ほとんどの PyPI ホイールは
libcudart.so.12にリンクしていますが、Spark は CUDA 13 を搭載しています。pip は CUDA ABI をチェックしないため、インポート時または最初のカーネル起動時に初めて表面化します。 - チェック:
references/gotcha-checks.mdG1 — ホイールの CUDA ビルドタグ。 - 修正:
download.pytorch.org/whl/cu130から再インストールするか、一致したコンテナを使用します。
G2: flash-attn — pip ビルドをスキップし、Unsloth の自動検出に注意
- 症状:
pip install flash-attnが依然として失敗またはハングします。また Unsloth は、明示的に要求された SDPA を無視して flash-attn で学習することがあります。 - 原因: 素の pip 用の aarch64/sm_121 ホイールは存在しませんが、NGC コンテナには動作する SM121 flash-attn が同梱されており、Unsloth はそれを自動的に優先して
attn_implementation="sdpa"を破棄します。 - チェック:
references/gotcha-checks.mdG2 — flash-attn がすでに存在して動作しているか。 - 修正: 素の pip の場合 — flash-attn をスキップし、SDPA を使用します(変更なし)。NGC の場合 — 唯一信頼できる上書きは
references/gotcha-checks.mdG2 のモンキーパッチです。
G3: 128GB 未満での UMA OOM
- 症状:
nvidia-smiが 128GB の上限未満の空きメモリを依然として報告しているのに、モデルのロード/トレーニング中に OOM になる — あるいは一部の構成では、数値ではなく[N/A]がそのまま表示されます。 - 原因: safetensors のロード中に mmap と CUDA アロケータがページを二重にカウントします。QLoRA は逆量子化が一時的な割り当てを追加するため、bf16 よりも早く OOM になることがあります。
- チェック:
references/gotcha-checks.mdG3 —nvidia-smiではなくfree -gと/proc/meminfoを読みます。 - 修正:
sync; echo 3 > /proc/sys/vm/drop_cachesでページキャッシュを破棄します — root 権限が必要で、トレーニングの途中ではなく実行と実行の間のリセットです。
G4: 熱によるスロットリング
- 症状: 数時間にわたる実行の途中でスループットが低下する、または持続的な負荷でマシンが自然に再起動する。
- 原因: 持続的な消費電力は公称 240W に対して約 100W で頭打ちになります。長時間の実行はその天井に達し、スロットリング、時には再起動を引き起こします。
- チェック:
references/gotcha-checks.mdG4 —nvidia-smi --query-gpu=temperature.gpu,power.drawをサンプリングします。 - 修正: 温度が上昇する一方で電力が 240W 未満で頭打ちになる場合、スロットリングを原因とみなします。冷却を改善するか、実行時間を制限します。
G5: 帯域幅の上限
- 症状: メモリバウンドのワークロード、特にデコード中心の RL ループが、期待されるスループットを大きく下回って頭打ちになります。
- 原因: 273 GB/s は仕様上の上限であり、持続値ではありません。実測帯域幅は 180~192 GB/s です。
- 確認:
references/gotcha-checks.mdG5 — 観測されたステップ時間を、仕様ではなく実測範囲と比較します。 - 修正: スループットは 180~192 GB/s を前提に見積もってください。273 GB/s の数値に基づいて立てた計画は修正してください。
G6: グローバル UMA リソースの競合
- 症状: あるプロセスの KV キャッシュ/重みが実行中に黙って追い出され、そのプロセス自身のログには OOM が出ません。
- 原因: 統合メモリは単一のグローバルプールです。上限なし、または容量ぎりぎりのプロセスは他のあらゆるものと競合し、それを追い出すことがあります。小規模で上限を定めたワークロードは競合しません。<4GB の LoRA は、
gpu-memory-utilization<=0.5に制限した vLLM と問題なく共存します。 - 確認:
references/gotcha-checks.mdG6 — 他に GPU 上に常駐しているプロセスと、それらに上限が設定されているかどうか。 - 修正: 「重いジョブは 1 つ」というルールは上限なし、または容量ぎりぎりのワークロードに適用されます。まず無関係なサーバーを制限するか停止してください。小規模で上限を定めたワークロードは停止する必要はありません。
G7: SM121 では NVFP4 が FP8 より遅い
- 症状: Spark 上で推論ワークロードを FP8 から NVFP4 に切り替えると、速くなるどころか遅くなります。
- 原因: SM121 には
cvt.e2m1x2がありません。ただしカーネルがsm_121aをターゲットにしている場合は除きます。これがないと NVFP4 は約 32% 遅くなります。 - 確認:
references/gotcha-checks.mdG7 — capability が(12, 1)を報告します。ビルドはsm_121aをターゲットにしていますか? - 修正: ビルドが
sm_121aをターゲットにしていない限り、FP8 のままにしてください。
G8: 公式プレイブックの陳腐化
- 症状: 公式の DGX Spark プレイブックに従っても失敗し、それを説明するローカルの設定ミスも見当たりません。
- 原因: 公式プレイブックはこれまでにも壊れた状態で出荷されたことがあります。スタックはドキュメントより速く動きます。
- 確認:
references/gotcha-checks.mdG8 — プレイブックリポジトリの最近の issue。 - 修正: 高コストな実行のためにレシピを信頼する前に、
github.com/NVIDIA/dgx-spark-playbooksの issue を確認してください。
G9: bare pip ではなくコンテナ優先
- 症状: 昨日は動いていた bare pip 環境が、無関係な
pip installの後に壊れる。あるいは、「同一」のはずの 2 つの環境が異なる挙動を示します。 - 原因: bare pip では Triton、xformers、transformers がそれぞれ独立にずれていきます。それらを GB10 の SM121 ターゲットに固定するものは何もありません。
- 確認:
references/gotcha-checks.mdG9 — コンテナですか、それとも bare pip ですか? - 修正: NGC コンテナ(タグの指針は
spark-environment-setupを参照)または Unsloth のコンテナを優先してください。bare pip を避けられない場合は、Unsloth での--no-depsを含め、NVIDIA のインストール順序に従ってください。
G10: Dual-Spark は DDP/FSDP のみ
- 症状: 2 台の Spark にまたがるテンソル並列の起動がハングするか、シングル Spark よりはるかに遅く動作するか、エラーになります。
- 原因: ConnectX-7 は勾配/パラメータの同期(DDP、FSDP)には十分な速さですが、TP の細かいトラフィックには細すぎます。
- 確認:
references/gotcha-checks.mdG10 — 設定された並列化戦略。 - 修正: 2 台の Spark 構成では、DDP または FSDP を選び、テンソル並列は決して選ばないでください — ここでは TP はシングルノード専用です。
迅速なトリアージ
何よりもまず実行すべき、最も低コストな確認:
python3 -c "import torch; print(torch.version.cuda)" # expect 13.x (G1); NGC builds have no +cu130 tag — that's not a failure
import torch; print(torch.cuda.get_device_capability()) # expect (12, 1) (G7)
{ [ -f /.dockerenv -o -f /run/.containerenv ] || grep -qE 'docker|containerd' /proc/1/cgroup; } 2>/dev/null && echo container || echo unknown # G9
assets/preflight.sh は G1、G3、G4、G7、G9 を実行し、gotcha ごとに 1 行の出力を固定フォーマットで生成します。まず G 番号、次に自動化可能な場合は PASS/FAIL/WARN、利用できない場合は SKIP、生の読み取り値(G3、G4)の場合は INFO: です。コマンドの全体は references/gotcha-checks.md にあります。動作する前提の環境については spark-environment-setup も参照してください。
コメント
Markdown 対応