mcpField
N
nemo-mbridge-perf-cuda-graphs

nemo-mbridge-perf-cuda-graphs

github.com/promptingcompany开发039 次安装17 周前更新
代码仓库

关于 nemo-mbridge-perf-cuda-graphs

面向 NeMo Megatron Bridge 训练的 CUDA Graphs 配置与基准测试指南,涵盖 local 全迭代捕获和 Transformer Engine 分范围捕获,并说明适用限制与验证步骤。

主要功能

  1. 01配置 local 全迭代图
  2. 02配置 Transformer Engine 分范围图
  3. 03按模型类型选择范围
  4. 04设置性能测试工具
  5. 05了解兼容性与显存限制

适用场景

  1. 01降低训练中的主机开销
  2. 02为 dense 或 MoE 模型选择图范围
  3. 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.md
card.yaml
skill-card.md
skill.oms.sig
evals/
evals.json

详细介绍

CUDA Graphs

稳定版文档:@docs/training/cuda-graphs.md 卡片:@skills/nemo-mbridge-perf-cuda-graphs/card.yaml

概述

CUDA Graphs 会捕获一次 GPU 操作,并以极低的主机驱动开销重放。Bridge 支持两种实现:

cuda_graph_impl机制支持的范围
"local"MCore FullCudaGraphWrapper 包装整个前向和反向传播full_iteration
"transformer_engine"对每一层使用 TE make_graphed_callables()attn、mlp、moe、moe_router、moe_preprocess、mamba

快速决策

对于大多数训练工作负载,先使用 TE 范围图,再在相同的分发器、布局和容器中,将重放计时与即时执行进行比较:

  • 稠密模型:attn,然后可选地使用 mlp
  • 无丢弃 MoE:attn moe_router moe_preprocess
  • VLM:使用相同的无丢弃 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 范围图(稠密模型)
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 中强制执行)
  • 仅当 cuda_graph_impl = "local" 时,才能使用 full_iteration 范围
  • full_iteration 范围要求 check_for_nan_in_loss = False
  • 不要同时使用 moe 范围和 moe_router 范围
  • 张量形状必须固定(固定的 seq_length、固定的 micro_batch_size)
  • MoE 无丢弃路由会将可绘制图的范围限制为稠密模块
  • 使用 PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True 时,设置 NCCL_GRAPH_REGISTER=0(MCore 会针对架构低于 sm_100 的设备在 local 实现中强制执行;TE 实现则无条件断言)
  • CPU 卸载与 CUDA graphs 不兼容
  • moe_preprocess 范围要求同时设置 moe_router 范围
实际启用顺序
  1. 先稳定即时执行。
  2. 固定序列长度和微批次大小。
  3. 启用范围尽可能窄且有用的图。
  4. 确认重放已启用,且内存仍在可接受范围内。
  5. 预热和捕获后,比较即时执行与图重放迭代;不要将捕获步骤计入稳态计时。
  6. 只有此时才扩大范围,或与重叠功能结合。

代码位置

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 tracker 要求
        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 graph 的交互
            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.py
  • TECudaGraphHelper:megatron/core/transformer/cuda_graphs.py
  • FullCudaGraphWrapper:megatron/core/full_cuda_graph.py
  • CudaGraphScope 枚举:megatron/core/transformer/enums.py
推荐配置参考
  • scripts/performance/configs/deepseek/deepseek_workload_base_configs.py
  • scripts/performance/configs/qwen/qwen3_workload_base_configs.py
  • scripts/performance/configs/gpt_oss/gpt_oss_workload_base_configs.py
测试
文件覆盖范围
tests/unit_tests/training/test_config.pyfull_iteration NaN 检查约束
tests/unit_tests/training/test_comm_overlap.pydelay_wgrad 与 CUDA 图的交互
tests/unit_tests/models/test_gpt_full_te_layer_autocast_spec.pyCUDA 图中的 TE 自动转换
tests/functional_tests/recipes/test_llama_recipes_pretrain_cuda_graphs.py端到端本地和 TE 图冒烟测试
tests/unit_tests/recipes/kimi/test_kimi_k2.pyTE + CUDA 图配方配置
tests/unit_tests/recipes/gpt/test_gpt3_175b.pyTE + CUDA 图配方配置
tests/unit_tests/recipes/qwen_vl/test_qwen25_vl_recipes.pyVLM CUDA 图设置

注意事项

  1. TE RNG 跟踪器是必需的:设置 cuda_graph_impl 时,如果未设置 use_te_rng_tracker=True 和 rng.te_rng_tracker=True,provider 中会触发断言。

  2. full_iteration 要求禁用 NaN 检查:捕获范围涵盖整个 fwd+bwd,因此无法通过损失 NaN 检查来检查中间值。

  3. MoE 范围限制:moe 范围与 moe_router 范围互斥。无丢弃 Token 的 MoE 只能对 moe_router 和 moe_preprocess 创建图,不能对完整的专家分发过程创建图。

  4. 内存开销:CUDA 图会在其生命周期内固定所有中间缓冲区(不复用内存)。TE 范围图会额外占用数 GB 内存; 完整迭代图可能使峰值内存增加 1.5–2 倍。PP > 1 会加剧开销,因为每个阶段都有自己的图。

  5. 延迟 wgrad 的影响:当 delay_wgrad_compute=True 且 attention 或 MoE router 位于 cuda_graph_scope 中时, 还需满足以下条件:TE >= 2.12.0、gradient_accumulation_fusion=True,并且不能有 attention bias。

  6. 可变长度序列会破坏图:各步的序列长度必须保持不变。如果需要打包,请使用填充后的打包序列。

  7. 必须清理图:CUDA 图对象会持有 NCCL 缓冲区引用。Bridge 会在训练结束时通过 _delete_cuda_graphs() 处理此问题, 但提前退出时必须显式调用该函数。

  8. 较旧的 GPU 架构:在计算能力 < 10.0 的 GPU(Blackwell 之前的架构)上,如果使用 PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True,请设置 NCCL_GRAPH_REGISTER=0。MCore CudaGraphManager(cuda_graphs.py:1428)和 TECudaGraphHelper (cuda_graphs.py:1697)会强制执行此要求。无论架构如何,TE 实现都会无条件触发断言。

  9. 与 CPU 卸载不兼容:CUDA 图不能与 CPU 卸载一起使用。MCore 在 transformer_config.py:1907 中强制执行此限制。

  10. MoE 重计算 + moe_router 范围:使用 cuda_graph_impl = "transformer_engine" 时,MoE 重计算不支持 moe_router CUDA 图范围。MCore 在 transformer_config.py:1977 中强制执行此限制。

  11. 层级重计算要求使用 full_iteration 范围:使用 recompute_granularity="full" 和 recompute_num_layers(重计算 N 个完整 Transformer 层)时,与 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。

  12. 基准测试数据因工作负载而异:当主机开销明显时,图通常确实能带来收益,但具体收益取决于批次形状、PP 深度、重计算、分发器后端,以及 eager 基线是否已经过优化。

  13. 成功捕获不保证加速:2026-05-18,在 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 错误或非法内存访问。

评论

支持 Markdown