nemo-mbridge-perf-cuda-graphs について
NeMo Megatron Bridgeの学習でCUDA Graphsを設定・評価するスキルです。localの全イテレーション捕捉とTransformer Engineのスコープ別捕捉を扱い、制約や検証手順も説明します。
主な機能
- 01local全イテレーションの設定
- 02Transformer Engineのスコープ別グラフ
- 03モデル別のスコープ選択
- 04性能ハーネスの設定
- 05互換性とメモリ制約の確認
活用シーン
- 01学習時のホスト処理負荷の軽減
- 02denseモデルやMoEモデルのスコープ選択
- 03グラフ再生とeager実行の速度比較
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ promptingcompany/ nv-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 は 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
推奨設定の参照先
scripts/performance/configs/deepseek/deepseek_workload_base_configs.pyscripts/performance/configs/qwen/qwen3_workload_base_configs.pyscripts/performance/configs/gpt_oss/gpt_oss_workload_base_configs.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/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/recipes/test_llama_recipes_pretrain_cuda_graphs.py -q
成功基準
localとtransformer_engineの両実装について、設定の検証を網羅したユニットテストが成功します。- 機能テストで、両方の CUDA グラフ実装を使用したトレーニングステップが完了します。
- ログに NCCL エラーや不正なメモリアクセスがありません。