Skip to content

Commit d0debd0

Browse files
perf(nemotron): enable CuteDSL fusion for GB MXFP8 (#5620)
Signed-off-by: Malay Nagda <malayn@nvidia.com> Co-authored-by: Kamran Jafari <kjafarisadeg@nvidia.com>
1 parent 96db955 commit d0debd0

5 files changed

Lines changed: 144 additions & 14 deletions

File tree

‎src/megatron/bridge/perf_recipes/nemotronh/gb200/nemotronh.py‎

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,9 @@ def nemotron_3_super_pretrain_64gpu_gb200_fp8mx_config() -> ConfigContainer:
143143
cfg.model.cuda_graph_scope = ["attn", "mamba", "moe_router", "moe_preprocess"]
144144

145145
_apply_nemotron_3_super_perf_defaults(cfg)
146+
cfg.model.use_transformer_engine_op_fuser = True
147+
cfg.model.moe_mlp_glu_interleave_size = 32
148+
cfg.mixed_precision.fp8_dot_product_attention = True
146149
# Keep process settings next to the recipe so users can see the exact benchmark environment.
147150
cfg.env_vars = {
148151
**COMMON_PERF_ENV_VARS,
@@ -160,7 +163,9 @@ def nemotron_3_super_pretrain_64gpu_gb200_fp8mx_config() -> ConfigContainer:
160163
"NVLINK_DOMAIN_SIZE": 72,
161164
"USE_MNNVL": 1,
162165
# Transformer Engine overlap settings for this model.
166+
"CUDNNFE_CLUSTER_OVERLAP_MARGIN": 8,
163167
"NVTE_BWD_LAYERNORM_SM_MARGIN": 20,
168+
"NVTE_CUTEDSL_FUSED_GROUPED_MLP": 1,
164169
"NVTE_FWD_LAYERNORM_SM_MARGIN": 20,
165170
}
166171
return cfg
@@ -354,8 +359,7 @@ def nemotron_3_nano_pretrain_8gpu_gb200_bf16_config() -> ConfigContainer:
354359
return cfg
355360

356361

357-
def nemotron_3_nano_pretrain_8gpu_gb200_fp8mx_config() -> ConfigContainer:
358-
"""Nemotron 3 Nano pretrain: 8× GB200, MXFP8."""
362+
def _build_nemotron_3_nano_gb200_mxfp8() -> ConfigContainer:
359363
cfg = nemotron_3_nano_pretrain_config()
360364
_apply_nemotron_3_nano_perf_defaults(cfg)
361365
cfg.mixed_precision = _perf_precision("fp8_mx")
@@ -379,6 +383,15 @@ def nemotron_3_nano_pretrain_8gpu_gb200_fp8mx_config() -> ConfigContainer:
379383

380384
_benchmark_common(cfg)
381385
cfg.model.moe_hybridep_num_sms = 32
386+
return cfg
387+
388+
389+
def nemotron_3_nano_pretrain_8gpu_gb200_fp8mx_config() -> ConfigContainer:
390+
"""Nemotron 3 Nano pretrain: 8× GB200, MXFP8."""
391+
cfg = _build_nemotron_3_nano_gb200_mxfp8()
392+
cfg.model.use_transformer_engine_op_fuser = True
393+
cfg.model.moe_mlp_glu_interleave_size = 32
394+
cfg.mixed_precision.fp8_dot_product_attention = True
382395
# Keep process settings next to the recipe so users can see the exact benchmark environment.
383396
cfg.env_vars = {
384397
**COMMON_PERF_ENV_VARS,
@@ -396,7 +409,9 @@ def nemotron_3_nano_pretrain_8gpu_gb200_fp8mx_config() -> ConfigContainer:
396409
"NVLINK_DOMAIN_SIZE": 72,
397410
"USE_MNNVL": 1,
398411
# Transformer Engine overlap settings for this model.
412+
"CUDNNFE_CLUSTER_OVERLAP_MARGIN": 8,
399413
"NVTE_BWD_LAYERNORM_SM_MARGIN": 20,
414+
"NVTE_CUTEDSL_FUSED_GROUPED_MLP": 1,
400415
"NVTE_FWD_LAYERNORM_SM_MARGIN": 20,
401416
# Use cuDNN LayerNorm for this measured baseline.
402417
"NVTE_NORM_BWD_USE_CUDNN": 1,
@@ -489,9 +504,8 @@ def nemotron_3_5_lightning_pretrain_8gpu_gb200_bf16_config() -> ConfigContainer:
489504
return cfg
490505

491506

492-
def nemotron_3_5_lightning_pretrain_8gpu_gb200_fp8mx_config() -> ConfigContainer:
493-
"""Nemotron 3.5 Lightning pretrain: 8× GB200, MXFP8."""
494-
cfg = nemotron_3_nano_pretrain_8gpu_gb200_fp8mx_config()
507+
def _build_nemotron_3_5_lightning_gb200_mxfp8() -> ConfigContainer:
508+
cfg = _build_nemotron_3_nano_gb200_mxfp8()
495509
cfg.model.moe_hybridep_num_sms = 16
496510
cfg.model.mtp_num_layers = 2
497511
cfg.model.mtp_hybrid_override_pattern = "*E"
@@ -502,6 +516,15 @@ def nemotron_3_5_lightning_pretrain_8gpu_gb200_fp8mx_config() -> ConfigContainer
502516
cfg.model.hf_model_revision = _NEMOTRON_3_5_LIGHTNING_MODEL_REVISION
503517
cfg.tokenizer.tokenizer_model = _NEMOTRON_3_5_LIGHTNING_MODEL_ID
504518
cfg.tokenizer.hf_tokenizer_kwargs = {"revision": _NEMOTRON_3_5_LIGHTNING_MODEL_REVISION}
519+
return cfg
520+
521+
522+
def nemotron_3_5_lightning_pretrain_8gpu_gb200_fp8mx_config() -> ConfigContainer:
523+
"""Nemotron 3.5 Lightning pretrain: 8× GB200, MXFP8."""
524+
cfg = _build_nemotron_3_5_lightning_gb200_mxfp8()
525+
cfg.model.use_transformer_engine_op_fuser = True
526+
cfg.model.moe_mlp_glu_interleave_size = 32
527+
cfg.mixed_precision.fp8_dot_product_attention = True
505528
cfg.env_vars = {
506529
**COMMON_PERF_ENV_VARS,
507530
"CUDA_DEVICE_MAX_CONNECTIONS": 32,
@@ -513,7 +536,9 @@ def nemotron_3_5_lightning_pretrain_8gpu_gb200_fp8mx_config() -> ConfigContainer
513536
"NUM_OF_TOKENS_PER_CHUNK_COMBINE_API": 128,
514537
"NVLINK_DOMAIN_SIZE": 72,
515538
"USE_MNNVL": 1,
539+
"CUDNNFE_CLUSTER_OVERLAP_MARGIN": 8,
516540
"NVTE_BWD_LAYERNORM_SM_MARGIN": 20,
541+
"NVTE_CUTEDSL_FUSED_GROUPED_MLP": 1,
517542
"NVTE_FWD_LAYERNORM_SM_MARGIN": 20,
518543
"NVTE_NORM_BWD_USE_CUDNN": 1,
519544
"NVTE_NORM_FWD_USE_CUDNN": 1,
@@ -523,7 +548,7 @@ def nemotron_3_5_lightning_pretrain_8gpu_gb200_fp8mx_config() -> ConfigContainer
523548

524549
def nemotron_3_5_lightning_pretrain_8gpu_gb200_fp8mx_fsdp_config() -> ConfigContainer:
525550
"""Nemotron 3.5 Lightning pretrain: 8× GB200, MXFP8, Megatron FSDP."""
526-
cfg = nemotron_3_5_lightning_pretrain_8gpu_gb200_fp8mx_config()
551+
cfg = _build_nemotron_3_5_lightning_gb200_mxfp8()
527552

528553
# FSDP reduces the model-state footprint enough to use the larger measured
529554
# microbatch. Megatron FSDP registers module hooks that Transformer Engine

‎src/megatron/bridge/perf_recipes/nemotronh/gb300/nemotronh.py‎

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,7 @@ def nemotron_3_super_pretrain_64gpu_gb300_bf16_config() -> ConfigContainer:
115115
return cfg
116116

117117

118-
def nemotron_3_super_pretrain_64gpu_gb300_fp8mx_config() -> ConfigContainer:
119-
"""Nemotron 3 Super pretrain: 64× GB300, MXFP8."""
118+
def _build_nemotron_3_super_gb300_mxfp8() -> ConfigContainer:
120119
cfg = nemotron_3_super_pretrain_config()
121120
cfg.mixed_precision = _perf_precision("fp8_mx")
122121

@@ -139,6 +138,15 @@ def nemotron_3_super_pretrain_64gpu_gb300_fp8mx_config() -> ConfigContainer:
139138
cfg.model.cuda_graph_scope = ["attn", "mamba", "moe_router", "moe_preprocess"]
140139

141140
_apply_nemotron_3_super_perf_defaults(cfg)
141+
return cfg
142+
143+
144+
def nemotron_3_super_pretrain_64gpu_gb300_fp8mx_config() -> ConfigContainer:
145+
"""Nemotron 3 Super pretrain: 64× GB300, MXFP8."""
146+
cfg = _build_nemotron_3_super_gb300_mxfp8()
147+
cfg.model.use_transformer_engine_op_fuser = True
148+
cfg.model.moe_mlp_glu_interleave_size = 32
149+
cfg.mixed_precision.fp8_dot_product_attention = True
142150
# Keep process settings next to the recipe so users can see the exact benchmark environment.
143151
cfg.env_vars = {
144152
**COMMON_PERF_ENV_VARS,
@@ -156,7 +164,9 @@ def nemotron_3_super_pretrain_64gpu_gb300_fp8mx_config() -> ConfigContainer:
156164
"NVLINK_DOMAIN_SIZE": 72,
157165
"USE_MNNVL": 1,
158166
# Transformer Engine overlap settings for this model.
167+
"CUDNNFE_CLUSTER_OVERLAP_MARGIN": 8,
159168
"NVTE_BWD_LAYERNORM_SM_MARGIN": 20,
169+
"NVTE_CUTEDSL_FUSED_GROUPED_MLP": 1,
160170
"NVTE_FWD_LAYERNORM_SM_MARGIN": 20,
161171
}
162172
return cfg
@@ -359,8 +369,7 @@ def nemotron_3_nano_pretrain_8gpu_gb300_bf16_config() -> ConfigContainer:
359369
return cfg
360370

361371

362-
def nemotron_3_nano_pretrain_8gpu_gb300_fp8mx_config() -> ConfigContainer:
363-
"""Nemotron 3 Nano pretrain: 8× GB300, MXFP8."""
372+
def _build_nemotron_3_nano_gb300_mxfp8() -> ConfigContainer:
364373
cfg = nemotron_3_nano_pretrain_config()
365374
_apply_nemotron_3_nano_perf_defaults(cfg)
366375
cfg.mixed_precision = _perf_precision("fp8_mx")
@@ -384,6 +393,15 @@ def nemotron_3_nano_pretrain_8gpu_gb300_fp8mx_config() -> ConfigContainer:
384393

385394
_benchmark_common(cfg)
386395
cfg.model.moe_hybridep_num_sms = 16
396+
return cfg
397+
398+
399+
def nemotron_3_nano_pretrain_8gpu_gb300_fp8mx_config() -> ConfigContainer:
400+
"""Nemotron 3 Nano pretrain: 8× GB300, MXFP8."""
401+
cfg = _build_nemotron_3_nano_gb300_mxfp8()
402+
cfg.model.use_transformer_engine_op_fuser = True
403+
cfg.model.moe_mlp_glu_interleave_size = 32
404+
cfg.mixed_precision.fp8_dot_product_attention = True
387405
# Keep process settings next to the recipe so users can see the exact benchmark environment.
388406
cfg.env_vars = {
389407
**COMMON_PERF_ENV_VARS,
@@ -401,7 +419,9 @@ def nemotron_3_nano_pretrain_8gpu_gb300_fp8mx_config() -> ConfigContainer:
401419
"NVLINK_DOMAIN_SIZE": 72,
402420
"USE_MNNVL": 1,
403421
# Transformer Engine overlap settings for this model.
422+
"CUDNNFE_CLUSTER_OVERLAP_MARGIN": 8,
404423
"NVTE_BWD_LAYERNORM_SM_MARGIN": 20,
424+
"NVTE_CUTEDSL_FUSED_GROUPED_MLP": 1,
405425
"NVTE_FWD_LAYERNORM_SM_MARGIN": 20,
406426
# Use cuDNN LayerNorm for this measured baseline.
407427
"NVTE_NORM_BWD_USE_CUDNN": 1,

‎src/megatron/bridge/perf_recipes/nemotronh/vr200/nemotronh.py‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@
1818
ConfigContainer,
1919
)
2020
from megatron.bridge.perf_recipes.nemotronh.gb300.nemotronh import (
21+
_build_nemotron_3_nano_gb300_mxfp8,
22+
_build_nemotron_3_super_gb300_mxfp8,
2123
nemotron_3_nano_pretrain_8gpu_gb300_bf16_config,
22-
nemotron_3_nano_pretrain_8gpu_gb300_fp8mx_config,
2324
nemotron_3_nano_pretrain_8gpu_gb300_nvfp4_config,
2425
nemotron_3_super_pretrain_64gpu_gb300_bf16_config,
25-
nemotron_3_super_pretrain_64gpu_gb300_fp8mx_config,
2626
nemotron_3_super_pretrain_64gpu_gb300_nvfp4_config,
2727
)
2828

@@ -58,7 +58,7 @@ def nemotron_3_nano_pretrain_8gpu_vr200_bf16_config() -> ConfigContainer:
5858

5959
def nemotron_3_nano_pretrain_8gpu_vr200_fp8mx_config() -> ConfigContainer:
6060
"""Nemotron 3 Nano pretrain: 8× VR200, FP8-MX (alias of GB300)."""
61-
cfg = nemotron_3_nano_pretrain_8gpu_gb300_fp8mx_config()
61+
cfg = _build_nemotron_3_nano_gb300_mxfp8()
6262
# Keep process settings next to the recipe so users can see the exact benchmark environment.
6363
cfg.env_vars = {
6464
**COMMON_PERF_ENV_VARS,
@@ -144,7 +144,7 @@ def nemotron_3_super_pretrain_64gpu_vr200_bf16_config() -> ConfigContainer:
144144

145145
def nemotron_3_super_pretrain_64gpu_vr200_fp8mx_config() -> ConfigContainer:
146146
"""Nemotron 3 Super pretrain: 64× VR200, FP8-MX (alias of GB300)."""
147-
cfg = nemotron_3_super_pretrain_64gpu_gb300_fp8mx_config()
147+
cfg = _build_nemotron_3_super_gb300_mxfp8()
148148
# Keep process settings next to the recipe so users can see the exact benchmark environment.
149149
cfg.env_vars = {
150150
**COMMON_PERF_ENV_VARS,

‎tests/unit_tests/recipes/test_nemotron_3_5_lightning_perf_recipes.py‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,36 @@ def test_nemotron_3_5_perf_recipes_inherit_nemotron_3_policy(
188188
assert cfg.tokenizer.tokenizer_model != base_cfg.tokenizer.tokenizer_model
189189

190190

191+
def test_gb200_mxfp8_enables_cutedsl_fusion() -> None:
192+
"""The non-FSDP Lightning recipe enables CutDSL without MoE A2A overlap."""
193+
cfg = nemotron_3_5_lightning_pretrain_8gpu_gb200_fp8mx_config()
194+
195+
assert cfg.env_vars["NVTE_CUTEDSL_FUSED_GROUPED_MLP"] == 1
196+
assert cfg.env_vars["CUDNNFE_CLUSTER_OVERLAP_MARGIN"] == 8
197+
assert cfg.model.use_transformer_engine_op_fuser is True
198+
assert cfg.model.moe_mlp_glu_interleave_size == 32
199+
assert cfg.model.high_priority_a2a_comm_stream is False
200+
assert cfg.model.moe_hybridep_num_sms_preprocessing == 108
201+
assert cfg.mixed_precision.fp8_dot_product_attention is True
202+
assert cfg.comm_overlap.overlap_moe_expert_parallel_comm is False
203+
assert cfg.comm_overlap.delay_wgrad_compute is False
204+
205+
206+
def test_gb200_mxfp8_fsdp_skips_cutedsl_fusion() -> None:
207+
"""The Lightning MXFP8 FSDP variant remains outside the CutDSL tuning scope."""
208+
cfg = nemotron_3_5_lightning_pretrain_8gpu_gb200_fp8mx_fsdp_config()
209+
210+
assert "NVTE_CUTEDSL_FUSED_GROUPED_MLP" not in cfg.env_vars
211+
assert "CUDNNFE_CLUSTER_OVERLAP_MARGIN" not in cfg.env_vars
212+
assert getattr(cfg.model, "use_transformer_engine_op_fuser", False) is False
213+
assert getattr(cfg.model, "moe_mlp_glu_interleave_size", None) is None
214+
assert getattr(cfg.model, "high_priority_a2a_comm_stream", False) is False
215+
assert getattr(cfg.model, "moe_hybridep_num_sms_preprocessing", None) != 32
216+
assert cfg.mixed_precision.fp8_dot_product_attention is False
217+
assert cfg.comm_overlap.overlap_moe_expert_parallel_comm is False
218+
assert cfg.comm_overlap.delay_wgrad_compute is False
219+
220+
191221
@pytest.mark.parametrize("recipe_factory", _H100_RECIPES, ids=lambda recipe: recipe.__name__)
192222
def test_h100_perf_recipe_topology(recipe_factory: Callable[[], ConfigContainer]) -> None:
193223
"""H100 Nemotron 3.5 Lightning variants retain the established performance topology."""

‎tests/unit_tests/recipes/test_nemotronh_recipes.py‎

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ class _FakeModelProvider:
5454

5555
def __init__(self) -> None:
5656
self.vocab_size = 256
57+
self.high_priority_a2a_comm_stream = False
58+
self.moe_hybridep_num_sms_preprocessing = 108
5759

5860
def finalize(self) -> None:
5961
return None
@@ -162,6 +164,59 @@ def test_nemotron_3_nano_gb200_defers_vocab_size_to_training_tokenizer():
162164
assert cfg.model.vocab_size is None
163165

164166

167+
@pytest.mark.parametrize(
168+
("module_name", "factory_name", "has_comm_overlap"),
169+
[
170+
pytest.param(
171+
"megatron.bridge.perf_recipes.nemotronh.gb200.nemotronh",
172+
"nemotron_3_nano_pretrain_8gpu_gb200_fp8mx_config",
173+
True,
174+
id="nano-gb200",
175+
),
176+
pytest.param(
177+
"megatron.bridge.perf_recipes.nemotronh.gb300.nemotronh",
178+
"nemotron_3_nano_pretrain_8gpu_gb300_fp8mx_config",
179+
True,
180+
id="nano-gb300",
181+
),
182+
pytest.param(
183+
"megatron.bridge.perf_recipes.nemotronh.gb200.nemotronh",
184+
"nemotron_3_super_pretrain_64gpu_gb200_fp8mx_config",
185+
False,
186+
id="super-gb200",
187+
),
188+
pytest.param(
189+
"megatron.bridge.perf_recipes.nemotronh.gb300.nemotronh",
190+
"nemotron_3_super_pretrain_64gpu_gb300_fp8mx_config",
191+
False,
192+
id="super-gb300",
193+
),
194+
],
195+
)
196+
def test_nemotron_3_gb_mxfp8_perf_recipes_enable_cutedsl_fusion(
197+
module_name: str,
198+
factory_name: str,
199+
has_comm_overlap: bool,
200+
) -> None:
201+
"""GB MXFP8 recipes match the measured CutDSL and MoE overlap settings."""
202+
module = importlib.import_module(module_name)
203+
cfg = getattr(module, factory_name)()
204+
205+
assert cfg.env_vars["NVTE_CUTEDSL_FUSED_GROUPED_MLP"] == 1
206+
assert cfg.env_vars["CUDNNFE_CLUSTER_OVERLAP_MARGIN"] == 8
207+
assert cfg.model.use_transformer_engine_op_fuser is True
208+
assert cfg.model.moe_mlp_glu_interleave_size == 32
209+
assert cfg.model.high_priority_a2a_comm_stream is False
210+
assert cfg.model.moe_hybridep_num_sms_preprocessing == 108
211+
assert cfg.mixed_precision.fp8_dot_product_attention is True
212+
if has_comm_overlap:
213+
assert cfg.comm_overlap is not None
214+
assert cfg.comm_overlap.overlap_moe_expert_parallel_comm is False
215+
assert cfg.comm_overlap.delay_wgrad_compute is False
216+
else:
217+
assert cfg.comm_overlap is None
218+
219+
165220
def test_nemotron_3_super_64gpu_gb200_matches_benchmark_hardware_configuration():
166221
"""The training recipe should share the tuned GB200 layout without benchmark-only behavior."""
167222
from megatron.bridge.perf_recipes.nemotronh.gb200.nemotronh import (

0 commit comments

Comments
 (0)