nemo-mbridge-perf-cuda-graphs について
Megatron Bridge の学習で CUDA グラフを設定・検証するためのスキルガイドです。ローカルの全イテレーションキャプチャと Transformer Engine のスコープ別キャプチャを扱い、学習エンジニアが適用可否を判断するための制約と計測方法を説明します。
主な機能
- 01ローカル全イテレーションキャプチャ
- 02Transformer Engine のスコープ別グラフ
- 03設定と制約のガイダンス
- 04パフォーマンスハーネスの設定
- 05リプレイ時間の検証
活用シーン
- 01学習時のホストドライバー負荷の低減
- 02密モデルや MoE モデルのスコープ選択
- 03グラフリプレイと eager の時間比較
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ nvidia/ skills --skill nemo-mbridge-perf-cuda-graphsインストール後、Claude Code で/nemo-mbridge-perf-cuda-graphsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
BENCHMARK.mdcard.yamlskill-card.mdskill.oms.sigevals/evals.json詳細
CUDA グラフ
安定版ドキュメント:@docs/training/cuda-graphs.md カード:@skills/nemo-mbridge-perf-cuda-graphs/card.yaml
概要
CUDA グラフは GPU 操作を一度キャプチャし、ホストドライバーのオーバーヘッドを最小限に抑えて再実行します。Bridge は 2 つの実装をサポートしています。
cuda_graph_impl | 仕組み | スコープのサポート |
|---|---|---|
"local" | MCore の FullCudaGraphWrapper で fwd+bwd 全体をラップ | full_iteration |
"transformer_engine" | レイヤーごとに TE の make_graphed_callables() を使用 | attn、mlp、moe、moe_router、moe_preprocess、mamba |
すぐに判断する
多くのトレーニングワークロードでは、まず TE スコープのグラフから始め、同じディスパッチャー、レイアウト、コンテナーで eager と再実行の時間を比較してください。
- dense モデル:
attn、次に必要に応じてmlp - dropless MoE:
attn moe_router moe_preprocess - VLM:同じ dropless-MoE スコープ。ただし、実データのパスが安定してから使用します
完全なイテレーションのキャプチャを明確に必要としており、より厳しい制約を満たせる場合に限り、local と full_iteration を使用してください。
再計算の多いワークロードの場合:
- TE スコープのグラフは選択的再計算と自然に組み合わせられます
- 完全な再計算では、通常、
localの完全なイテレーショングラフを使うか、グラフの使用を避けることになります
関連ドキュメント:
- @docs/training/cuda-graphs.md
- @docs/training/activation-recomputation.md
有効化
Local の完全なイテレーショングラフ
cfg.model.cuda_graph_impl = "local"
cfg.model.cuda_graph_scope = ["full_iteration"]
cfg.model.cuda_graph_warmup_steps = 3
cfg.model.use_te_rng_tracker = True
cfg.rng.te_rng_tracker = True
cfg.rerun_state_machine.check_for_nan_in_loss = False
cfg.ddp.check_for_nan_in_grad = False
TE スコープのグラフ(dense モデル)
cfg.model.cuda_graph_impl = "transformer_engine"
cfg.model.cuda_graph_scope = ["attn"] # or ["attn", "mlp"]
cfg.model.cuda_graph_warmup_steps = 3
cfg.model.use_te_rng_tracker = True
cfg.rng.te_rng_tracker = True
TE スコープのグラフ(MoE モデル)
cfg.model.cuda_graph_impl = "transformer_engine"
cfg.model.cuda_graph_scope = ["attn", "moe_router", "moe_preprocess"]
cfg.model.cuda_graph_warmup_steps = 3
cfg.model.use_te_rng_tracker = True
cfg.rng.te_rng_tracker = True
パフォーマンスハーネスの CLI
uv run python scripts/performance/run_script.py \
-m qwen \
-mr qwen3_30b_a3b \
--task pretrain \
-g h100 \
-c bf16 \
-ng 16 \
--cuda_graph_impl transformer_engine \
--cuda_graph_scope attn,moe_router,moe_preprocess \
...
有効な CLI 値は scripts/performance/argument_parser.py にあります。
VALID_CUDA_GRAPH_IMPLS:["none", "local", "transformer_engine"]VALID_CUDA_GRAPH_SCOPES:["full_iteration", "attn", "mlp", "moe", "moe_router", "moe_preprocess", "mamba"]
パフォーマンスハーネスでは、--cuda_graph_scope にカンマ区切りの値を指定します。また、--cuda_graph_impl が none 以外の場合は、model.use_te_rng_tracker と rng.te_rng_tracker を自動的に有効にします。
必須の制約
use_te_rng_tracker = True(gpt_provider.pyで強制されます)full_iterationスコープはcuda_graph_impl = "local"の場合にのみ使用できますfull_iterationスコープではcheck_for_nan_in_loss = Falseが必要ですmoeスコープとmoe_routerスコープを併用しないでください- テンソル形状は静的である必要があります(seq_length と micro_batch_size を固定)
- MoE のトークン脱落なしルーティングでは、グラフ化できるスコープが dense モジュールに限定されます
PYTORCH_CUDA_ALLOC_CONF=expandable_segments:Trueの場合は、NCCL_GRAPH_REGISTER=0を設定してください(MCore は arch < sm_100 で local 実装に対してこれを強制し、TE 実装では無条件にアサートします)- CPU オフロードは CUDA グラフと互換性がありません
moe_preprocessスコープを使用するには、moe_routerスコープも設定する必要があります
実用的な導入手順
- まず eager 実行を安定させます。
- シーケンス長とマイクロバッチサイズを固定します。
- 役立つ範囲で最も限定的なグラフスコープを有効にします。
- 再実行が有効になっていることと、メモリ使用量が許容範囲内であることを確認します。
- ウォームアップとキャプチャの後に、eager 実行とグラフ再実行のイテレーションを比較します。定常状態の計測にはキャプチャのステップを含めないでください。
- その後にのみ、スコープを広げるか、オーバーラップ機能と組み合わせます。
コードの参照箇所
Bridge の設定と検証
# CUDA graph scope validation: check_for_nan_in_loss must be disabled with full_iteration graph
if self.model.cuda_graph_impl == "local" and CudaGraphScope.full_iteration in self.model.cuda_graph_scope:
assert not self.rerun_state_machine.check_for_nan_in_loss, (
"check_for_nan_in_loss must be disabled when using full_iteration CUDA graph. "
"Set rerun_state_machine.check_for_nan_in_loss=False."
)
if self.model.cuda_graph_impl == "none":
self.model.cuda_graph_scope = []
TE RNG トラッカーの要件
if self.cuda_graph_impl != "none":
assert getattr(self, "use_te_rng_tracker", False), (
"Transformer engine's RNG tracker is required for cudagraphs, it can be "
"enabled with use_te_rng_tracker=True'."
トレーニングループでのグラフ作成とキャプチャ
# Capture CUDA Graphs.
cuda_graph_helper = None
if model_config.cuda_graph_impl == "transformer_engine":
cuda_graph_helper = TECudaGraphHelper(...)
# ...
if config.model.cuda_graph_impl == "local" and CudaGraphScope.full_iteration in config.model.cuda_graph_scope:
forward_backward_func = FullCudaGraphWrapper(
forward_backward_func, cuda_graph_warmup_steps=config.model.cuda_graph_warmup_steps
)
ウォームアップ後の TE グラフキャプチャ
# Capture CUDA Graphs after warmup.
if (
model_config.cuda_graph_impl == "transformer_engine"
and cuda_graph_helper is not None
and not cuda_graph_helper.graphs_created()
and global_state.train_state.step - start_iteration == model_config.cuda_graph_warmup_steps
):
if model_config.cuda_graph_warmup_steps > 0 and should_toggle_forward_pre_hook:
disable_forward_pre_hook(model, param_sync=False)
cuda_graph_helper.create_cudagraphs()
if model_config.cuda_graph_warmup_steps > 0 and should_toggle_forward_pre_hook:
enable_forward_pre_hook(model)
cuda_graph_helper.cuda_graph_set_manual_hooks()
RNG の初期化
_set_random_seed(
rng_config.seed,
rng_config.data_parallel_random_init,
rng_config.te_rng_tracker,
rng_config.inference_rng_tracker,
use_cudagraphable_rng=(model_config.cuda_graph_impl != "none"),
pg_collection=pg_collection,
)
遅延 wgrad と CUDA グラフの相互作用
cuda_graph_scope = getattr(model_cfg, "cuda_graph_scope", []) or []
# ... scope parsing ...
if wgrad_in_graph_scope:
assert is_te_min_version("2.12.0"), ...
assert model_cfg.gradient_accumulation_fusion, ...
if attn_scope_enabled:
assert not model_cfg.add_bias_linear and not model_cfg.add_qkv_bias, ...
パフォーマンスハーネスのオーバーライドヘルパー
def _set_cuda_graph_overrides(
recipe, cuda_graph_impl=None, cuda_graph_scope=None
):
# Sets impl, scope, and auto-enables te_rng_tracker
グラフのクリーンアップ
def _delete_cuda_graphs(cuda_graph_helper):
# Deletes FullCudaGraphWrapper and TE graph objects to free NCCL buffers
MCore クラス(3rdparty/Megatron-LM 内)
CudaGraphManager:megatron/core/transformer/cuda_graphs.pyTECudaGraphHelper:megatron/core/transformer/cuda_graphs.pyFullCudaGraphWrapper:megatron/core/full_cuda_graph.pyCudaGraphScopeenum:megatron/core/transformer/enums.py
推奨レシピの参照箇所
src/megatron/bridge/perf_recipes/deepseek/gb300/deepseek_v3.pysrc/megatron/bridge/perf_recipes/qwen/gb300/qwen3_moe.pysrc/megatron/bridge/perf_recipes/gpt_oss/gb300/gpt_oss.py
テスト
| ファイル | カバレッジ |
|---|---|
tests/unit_tests/training/test_config.py | full_iteration の NaN チェック制約 |
tests/unit_tests/training/test_comm_overlap.py | delay_wgrad と CUDA グラフの相互作用 |
tests/unit_tests/models/test_gpt_full_te_layer_autocast_spec.py | CUDA グラフでの TE オートキャスト |
tests/functional_tests/test_groups/recipes/test_llama_recipes_pretrain_cuda_graphs.py | ローカルおよび TE グラフのエンドツーエンドのスモークテスト |
tests/unit_tests/recipes/kimi/test_kimi_k2.py | TE と CUDA グラフのレシピ設定 |
tests/unit_tests/recipes/gpt/test_gpt3_175b.py | TE と CUDA グラフのレシピ設定 |
tests/unit_tests/recipes/qwen_vl/test_qwen25_vl_recipes.py | VLM の CUDA グラフ設定 |
注意点
-
TE RNG トラッカーは必須です:
use_te_rng_tracker=Trueとrng.te_rng_tracker=Trueを指定せずにcuda_graph_implを設定すると、 プロバイダーでアサートが発生します。 -
full_iterationでは NaN チェックを無効にする必要があります:fwd+bwd 全体を キャプチャするため、損失の NaN チェックでは中間値を検査できません。 -
MoE スコープの制限:
moeスコープとmoe_routerスコープは 併用できません。トークンをドロップしない MoE では、グラフ化できるのはmoe_routerとmoe_preprocessのみで、エキスパートのディスパッチ全体は グラフ化できません。 -
メモリーオーバーヘッド:CUDA グラフはグラフの存続期間中、すべての中間 バッファーを固定します(メモリーは再利用されません)。TE スコープのグラフでは 数 GB が追加され、イテレーション全体のグラフではピークメモリーが 1.5~2 倍に 増えることがあります。
PP > 1の場合、各ステージが独自のグラフを保持するため、 オーバーヘッドがさらに増加します。 -
遅延 wgrad との相互作用:
delay_wgrad_compute=Trueを設定し、attention または MoE router がcuda_graph_scopeに含まれる場合、追加の制約が適用されます: TE >= 2.12.0、gradient_accumulation_fusion=True、attention bias なし。 -
可変長シーケンスではグラフが動作しません:シーケンス長はステップ間で一定で ある必要があります。パッキングが必要な場合は、パディングしたパック済みシーケンスを 使用してください。
-
グラフのクリーンアップが必要です:CUDA グラフオブジェクトは NCCL バッファーへの 参照を保持します。Bridge はトレーニングの最後に
_delete_cuda_graphs()を呼び出して これを処理しますが、早期終了する場合は明示的に呼び出す必要があります。 -
古い GPU アーキテクチャ:compute capability < 10.0 (Blackwell より前)の GPU で
PYTORCH_CUDA_ALLOC_CONF=expandable_segments:Trueを 使用する場合は、NCCL_GRAPH_REGISTER=0を設定してください。MCore のCudaGraphManager(cuda_graphs.py:1428)とTECudaGraphHelper(cuda_graphs.py:1697)で適用されます。TE 実装ではアーキテクチャに関係なく 常にアサートが発生します。 -
CPU オフロードとは併用できません:CUDA グラフは CPU オフロードと併用できません。 MCore の
transformer_config.py:1907で適用されます。 -
MoE 再計算と moe_router スコープ:
cuda_graph_impl = "transformer_engine"を使用する場合、MoE 再計算はmoe_routerCUDA グラフ スコープではサポートされません。MCore のtransformer_config.py:1977で 適用されます。 -
レイヤーレベルの再計算には
full_iterationスコープが必要です:recompute_num_layers(トランスフォーマーレイヤー全体を N 個再計算する)とrecompute_granularity="full"を使用すると、TE スコープのグラフとは併用できません。 MCore では、再計算するレイヤー数を選択している場合でも、この粒度を「full」と呼びます。 この名前はモデル全体ではなく、レイヤー全体を再計算することを指します。TE スコープ (attn、mlp、moe_routerなど)を使用すると、次のアサートが発生します:AssertionError: full recompute is only supported with full iteration CUDA graph.これは、デフォルトで TE スコープのグラフを使用する FP8 構成(例:LLAMA3_70B_SFT_CONFIG_H100_FP8_CS_V1はcuda_graph_impl= "transformer_engine"、cuda_graph_scope="mlp"を使用)でよく発生します。対処方法: サブモジュール再計算(recompute_granularity="selective"とrecompute_modules)を 使用する、CUDA グラフを無効にする、またはlocalとfull_iterationに切り替えます。 MCore のtransformer_config.py:2001-2005で適用されます。詳細は @skills/nemo-mbridge-perf-activation-recompute/SKILL.md も参照してください。 -
ベンチマーク結果はワークロード固有です:ホストのオーバーヘッドが顕著な場合、 グラフ化による性能向上は通常実際に得られますが、具体的な向上幅はバッチ形状、PP の深さ、 再計算、ディスパッチャーのバックエンド、eager のベースラインがすでに最適化されていたか どうかによって異なります。
-
キャプチャに成功しても高速化が保証されるわけではありません:2026-05-18、 all-to-all ディスパッチャーを使用した Qwen3 30B A3B H100 BF16 の事前学習では、 TE スコープの
attn,moe_router,moe_preprocessグラフのキャプチャに成功しました (グラフ化可能なレイヤーは48、rank 0 でのキャプチャ時間は約6.9 s)。しかし、 再生イテレーション 5~8 の平均は42.00 sで、eager の41.36 sを上回りました。 スコープ付きグラフは初期導入時の候補として扱い、対象のスタックで検証してください。
検証
ユニットテスト
uv run python -m pytest \
tests/unit_tests/training/test_config.py -k "cuda_graph" \
tests/unit_tests/training/test_comm_overlap.py -k "cuda_graph" \
tests/unit_tests/models/test_gpt_full_te_layer_autocast_spec.py -k "cuda_graph" -q
機能スモークテスト(GPU が必要)
uv run python -m pytest \
tests/functional_tests/test_groups/recipes/test_llama_recipes_pretrain_cuda_graphs.py -q
成功基準
localとtransformer_engineの両実装について、設定の検証を網羅したユニットテストが成功します。- 機能テストで、両方の CUDA グラフ実装を使用したトレーニングステップが完了します。
- ログに NCCL エラーや不正なメモリアクセスがありません。