Skip to content

Commit 79abecd

Browse files
authored
feat(nemotron): Add GTP, Partial CG and NCCL-EP support for NT3 Ultra NVFP4 on GB200/GB300/VRNVL72 (#6468)
Signed-off-by: rghadia <rghadia@nvidia.com>
1 parent d45be7b commit 79abecd

6 files changed

Lines changed: 111 additions & 48 deletions

File tree

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

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,6 @@ def _nemotron_3_super_nvfp4_precision() -> MixedPrecisionConfig:
7474
def _nemotron_3_ultra_nvfp4_precision() -> MixedPrecisionConfig:
7575
"""Return the NVFP4 precision config used by Nemotron 3 Ultra perf recipes."""
7676
cfg = nemotron_3_ultra_bf16_with_nvfp4_mixed()
77-
# Although MCore PR 4358 is merged,
78-
# Megatron-FSDP's ParamAndGradBuffer has no NVFP4 packed-storage support, unlike the
79-
# legacy DDP buffer, so FP4 primary weights fault during buffer init.
80-
cfg.fp4_param_gather = False
8177
return cfg
8278

8379

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

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
ConfigContainer,
2121
_apply_nemotron_3_nano_perf_defaults,
2222
_apply_nemotron_3_super_perf_defaults,
23-
_apply_nemotron_3_ultra_fsdp_hsdp,
2423
_apply_nemotron_3_ultra_gtp,
2524
_apply_nemotron_3_ultra_perf_defaults,
2625
_benchmark_common,
@@ -293,29 +292,25 @@ def nemotron_3_ultra_pretrain_256gpu_gb200_fp8mx_config(*, num_gpus: int = 256)
293292

294293

295294
def nemotron_3_ultra_pretrain_256gpu_gb200_nvfp4_config(*, num_gpus: int = 256) -> ConfigContainer:
296-
"""Nemotron 3 Ultra (550B-A55B LatentMoE) pretrain: 256× GB200, NVFP4, Megatron-FSDP (HSDP).
295+
"""Nemotron 3 Ultra (550B-A55B LatentMoE) pretrain: 256× GB200, NVFP4, GTP.
297296
298297
TP2 + SP (due to smaller GB200 HBM) / PP1 / CP1 / EP64 / ETP1, GBS 256 / MBS 1, seq 8192, BF16 + NVFP4 mixed
299-
precision, HybridEP flex dispatcher, CuteDSL fused grouped MLP, selective recompute +
300-
fine-grained activation offload of the expert MLP, MTP=2.
298+
precision, dense GTP32, NCCLEP flex dispatcher with local attention/Mamba CUDA graphs, CuteDSL fused
299+
grouped MLP, selective recompute + fine-grained activation offload of the expert MLP, MTP=2.
301300
302301
Args:
303-
num_gpus: Launch GPU count used to size HSDP optimizer instances.
304-
Defaults to the canonical 256-GPU benchmark allocation.
302+
num_gpus: Retained for compatibility; sharding is rack-local and the
303+
distributed-optimizer instance count is fixed at one.
305304
"""
306305

307306
expert_model_parallel_size = 64
308307
global_batch_size = 256
309-
hybrid_ep_ranks_per_nvlink_domain = 64
310308

311309
cfg = nemotron_3_ultra_pretrain_config()
312310
cfg.mixed_precision = _nemotron_3_ultra_nvfp4_precision()
313311

314312
_apply_nemotron_3_ultra_perf_defaults(cfg)
315313

316-
# Apply HSDP / FSDP dtype overrides last so they win over the generic defaults.
317-
_apply_nemotron_3_ultra_fsdp_hsdp(cfg, num_gpus=num_gpus)
318-
319314
# Parallelism
320315
cfg.model.tensor_model_parallel_size = 2
321316
cfg.model.pipeline_model_parallel_size = 1
@@ -349,6 +344,21 @@ def nemotron_3_ultra_pretrain_256gpu_gb200_nvfp4_config(*, num_gpus: int = 256)
349344
cfg.model.recompute_granularity = "selective"
350345
cfg.model.recompute_modules = ["moe_act"]
351346

347+
# Shard dense weights with GTP within each 64-GPU rack. GTP currently
348+
# requires a single distributed-optimizer instance.
349+
_apply_nemotron_3_ultra_gtp(cfg)
350+
351+
cfg.model.cuda_graph_impl = "local"
352+
set_cuda_graph_modules(cfg.model, ["attn", "mamba"])
353+
# TODO: "moe_preprocess", "moe_router" needs to be disabled due to MCore PR 7046, performing a CPU-to-GPU copy for per token loss
354+
# TE attention requires TE's RNG tracker while MCore local graphs are capturing.
355+
cfg.rng.te_rng_tracker = cfg.model.use_te_rng_tracker = True
356+
357+
_enable_ncclep(cfg)
358+
# Device-side expert token counts: the legacy grouped MLP path syncs tokens_per_expert to the
359+
# host every layer, which serializes the CPU behind the GPU when dispatch is fast.
360+
cfg.model.moe_use_grouped_tensor = True
361+
352362
# Keep process settings next to the recipe so users can see the exact benchmark environment.
353363
cfg.env_vars = {
354364
**COMMON_PERF_ENV_VARS,
@@ -363,11 +373,8 @@ def nemotron_3_ultra_pretrain_256gpu_gb200_nvfp4_config(*, num_gpus: int = 256)
363373
"TORCH_NCCL_AVOID_RECORD_STREAMS": 1,
364374
# NCCL user-buffer and launch settings.
365375
"NCCL_NVLS_ENABLE": 0,
366-
# HybridEP topology for the target system.
367-
"NUM_OF_HYBRID_EP_RANKS_PER_NVLINK_DOMAIN": hybrid_ep_ranks_per_nvlink_domain,
368-
"NUM_OF_TOKENS_PER_CHUNK_COMBINE_API": 128,
369-
"NVLINK_DOMAIN_SIZE": 72,
370-
"USE_MNNVL": 1,
376+
# NCCL EP dispatcher mode and one GPU per rank.
377+
"NCCL_EP_HT_EM_PULL_PUSH": 1,
371378
# Transformer Engine overlap settings for this model.
372379
"NVTE_BWD_LAYERNORM_SM_MARGIN": 20,
373380
"NVTE_FWD_LAYERNORM_SM_MARGIN": 20,

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

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
ConfigContainer,
2121
_apply_nemotron_3_nano_perf_defaults,
2222
_apply_nemotron_3_super_perf_defaults,
23-
_apply_nemotron_3_ultra_fsdp_hsdp,
2423
_apply_nemotron_3_ultra_gtp,
2524
_apply_nemotron_3_ultra_perf_defaults,
2625
_benchmark_common,
@@ -320,15 +319,16 @@ def nemotron_3_ultra_pretrain_256gpu_gb300_fp8mx_config(*, num_gpus: int = 256)
320319

321320

322321
def nemotron_3_ultra_pretrain_256gpu_gb300_nvfp4_config(*, num_gpus: int = 256) -> ConfigContainer:
323-
"""Nemotron 3 Ultra (550B-A55B LatentMoE) pretrain: 256× GB300, NVFP4, Megatron-FSDP (HSDP).
322+
"""Nemotron 3 Ultra (550B-A55B LatentMoE) pretrain: 256× GB300, NVFP4, GTP.
324323
325324
TP1 / PP1 / CP1 / EP64 / ETP1, GBS 256 / MBS 1, seq 8192, BF16 + NVFP4 mixed
326-
precision, HybridEP flex dispatcher, CuteDSL fused grouped MLP, selective
327-
recompute + fine-grained activation offload of the expert MLP, MTP=2.
325+
precision, dense GTP64, NCCLEP flex dispatcher with local attention/Mamba CUDA
326+
graphs, CuteDSL fused grouped MLP, selective recompute + fine-grained activation
327+
offload of the expert MLP, MTP=2.
328328
329329
Args:
330-
num_gpus: Launch GPU count used to size HSDP optimizer instances.
331-
Defaults to the canonical 256-GPU benchmark allocation.
330+
num_gpus: Retained for compatibility; sharding is rack-local and the
331+
distributed-optimizer instance count is fixed at one.
332332
"""
333333

334334
expert_model_parallel_size = 64
@@ -371,8 +371,20 @@ def nemotron_3_ultra_pretrain_256gpu_gb300_nvfp4_config(*, num_gpus: int = 256)
371371

372372
_apply_nemotron_3_ultra_perf_defaults(cfg)
373373

374-
# Apply HSDP / FSDP dtype overrides last so they win over the generic defaults.
375-
_apply_nemotron_3_ultra_fsdp_hsdp(cfg, num_gpus=num_gpus)
374+
# Shard dense weights with GTP within each 64-GPU rack. GTP currently
375+
# requires a single distributed-optimizer instance.
376+
_apply_nemotron_3_ultra_gtp(cfg)
377+
378+
cfg.model.cuda_graph_impl = "local"
379+
set_cuda_graph_modules(cfg.model, ["attn", "mamba"])
380+
# TODO: "moe_preprocess", "moe_router" needs to be disabled due to MCore PR 7046, performing a CPU-to-GPU copy for per token loss
381+
# TE attention requires TE's RNG tracker while MCore local graphs are capturing.
382+
cfg.rng.te_rng_tracker = cfg.model.use_te_rng_tracker = True
383+
384+
_enable_ncclep(cfg)
385+
# Device-side expert token counts: the legacy grouped MLP path syncs tokens_per_expert to the
386+
# host every layer, which serializes the CPU behind the GPU when dispatch is fast.
387+
cfg.model.moe_use_grouped_tensor = True
376388

377389
# Keep process settings next to the recipe so users can see the exact benchmark environment.
378390
cfg.env_vars = {
@@ -385,11 +397,8 @@ def nemotron_3_ultra_pretrain_256gpu_gb300_nvfp4_config(*, num_gpus: int = 256)
385397
"TORCH_NCCL_AVOID_RECORD_STREAMS": 1,
386398
# NCCL user-buffer and launch settings.
387399
"NCCL_NVLS_ENABLE": 0,
388-
# HybridEP topology for the target system.
389-
"NUM_OF_HYBRID_EP_RANKS_PER_NVLINK_DOMAIN": 64,
390-
"NUM_OF_TOKENS_PER_CHUNK_COMBINE_API": 128,
391-
"NVLINK_DOMAIN_SIZE": 72,
392-
"USE_MNNVL": 1,
400+
# NCCL EP dispatcher mode and one GPU per rank.
401+
"NCCL_EP_HT_EM_PULL_PUSH": 1,
393402
# Transformer Engine overlap settings for this model.
394403
"NVTE_BWD_LAYERNORM_SM_MARGIN": 20,
395404
"NVTE_FWD_LAYERNORM_SM_MARGIN": 20,

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

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -260,8 +260,8 @@ def nemotron_3_ultra_pretrain_256gpu_vrnvl72_nvfp4_config(*, num_gpus: int = 256
260260
"""Nemotron 3 Ultra pretrain: 256× VRNVL72, NVFP4 (alias of GB300).
261261
262262
Args:
263-
num_gpus: Launch GPU count used to size HSDP optimizer instances.
264-
Defaults to the canonical 256-GPU benchmark allocation.
263+
num_gpus: Retained for compatibility; sharding is rack-local and the
264+
distributed-optimizer instance count is fixed at one.
265265
"""
266266
cfg = nemotron_3_ultra_pretrain_256gpu_gb300_nvfp4_config(num_gpus=num_gpus)
267267
# Keep process settings next to the recipe so users can see the exact benchmark environment.
@@ -275,11 +275,8 @@ def nemotron_3_ultra_pretrain_256gpu_vrnvl72_nvfp4_config(*, num_gpus: int = 256
275275
"TORCH_NCCL_AVOID_RECORD_STREAMS": 1,
276276
# NCCL user-buffer and launch settings.
277277
"NCCL_NVLS_ENABLE": 0,
278-
# Use 64 HybridEP ranks within the 72-GPU NVLink domain.
279-
"NUM_OF_HYBRID_EP_RANKS_PER_NVLINK_DOMAIN": 64,
280-
"NUM_OF_TOKENS_PER_CHUNK_COMBINE_API": 128,
281-
"NVLINK_DOMAIN_SIZE": 72,
282-
"USE_MNNVL": 1,
278+
# NCCL EP dispatcher mode and one GPU per rank.
279+
"NCCL_EP_HT_EM_PULL_PUSH": 1,
283280
# Transformer Engine overlap settings for this model.
284281
"NVTE_BWD_LAYERNORM_SM_MARGIN": 20,
285282
"NVTE_FWD_LAYERNORM_SM_MARGIN": 20,

‎tests/unit_tests/recipes/nemotronh/test_nemotron_3_ultra.py‎

Lines changed: 58 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@
1818
import torch
1919

2020
import megatron.bridge.recipes as recipes
21+
from megatron.bridge.perf_recipes.environment import HYBRID_EP_ENV_NAMES
2122
from megatron.bridge.perf_recipes.nemotronh import (
23+
nemotron_3_ultra_pretrain_256gpu_gb200_nvfp4_config,
24+
nemotron_3_ultra_pretrain_256gpu_gb300_nvfp4_config,
2225
nemotron_3_ultra_pretrain_256gpu_vrnvl72_fp8mx_config,
2326
nemotron_3_ultra_pretrain_256gpu_vrnvl72_nvfp4_config,
2427
)
@@ -36,6 +39,7 @@
3639
nemotron_3_ultra_pretrain_config,
3740
nemotron_3_ultra_sft_openmathinstruct2_packed_config,
3841
)
42+
from megatron.bridge.utils.cuda_graph import cuda_graph_module_names
3943
from tests.unit_tests.recipes.recipe_test_utils import (
4044
NEMOTRON_3_ULTRA_HYBRID_LAYER_PATTERN,
4145
patch_recipe_module_global,
@@ -202,23 +206,69 @@ def test_vrnvl72_nvfp4_perf_recipe_uses_nvl72_ultra_topology() -> None:
202206
assert cfg.model.expert_model_parallel_size == 64
203207
assert cfg.model.expert_tensor_parallel_size == 1
204208
assert cfg.model.moe_token_dispatcher_type == "flex"
205-
assert cfg.model.moe_flex_dispatcher_backend == "hybridep"
209+
assert cfg.model.moe_flex_dispatcher_backend == "ncclep"
210+
assert cfg.model.moe_use_grouped_tensor is True
206211
assert cfg.model.moe_router_padding_for_quantization is True
207-
assert cfg.model.cuda_graph_impl == "none"
212+
assert cfg.model.cuda_graph_impl == "local"
213+
assert cuda_graph_module_names(cfg.model) == ["attn", "mamba"]
214+
assert cfg.model.use_te_rng_tracker is True
215+
assert cfg.rng.te_rng_tracker is True
208216
assert cfg.mixed_precision.fp4 == "e2m1"
209-
assert cfg.mixed_precision.fp4_param_gather is False
217+
assert cfg.mixed_precision.fp4_param_gather is True
210218
assert cfg.train.global_batch_size == 256
211219
assert cfg.train.micro_batch_size == 1
212-
assert cfg.ddp.use_megatron_fsdp is True
213-
assert cfg.ddp.num_distributed_optimizer_instances == 4
214-
assert cfg.env_vars["NUM_OF_HYBRID_EP_RANKS_PER_NVLINK_DOMAIN"] == 64
215-
assert cfg.env_vars["NVLINK_DOMAIN_SIZE"] == 72
220+
assert cfg.dist.use_megatron_fsdp is False
221+
assert cfg.ddp.use_megatron_fsdp is False
222+
assert cfg.model.tensor_parallel_num_weight_shards == 64
223+
assert cfg.model.expert_tensor_parallel_num_weight_shards == 1
224+
assert cfg.ddp.num_distributed_optimizer_instances == 1
225+
assert cfg.env_vars["NCCL_EP_HT_EM_PULL_PUSH"] == 1
226+
assert cfg.env_vars.keys().isdisjoint(HYBRID_EP_ENV_NAMES)
216227
assert cfg.env_vars["NVTE_CPU_OFFLOAD_V1"] == 1
217228
assert cfg.env_vars["NVTE_CUTEDSL_FUSED_GROUPED_MLP"] == 1
218229
assert cfg.env_vars["NVTE_NORM_BWD_USE_CUDNN"] == 1
219230
assert cfg.env_vars["NVTE_NORM_FWD_USE_CUDNN"] == 1
220231
assert cfg.env_vars["NVTE_USE_FAST_MATH"] == 1
221-
assert cfg.env_vars["USE_MNNVL"] == 1
232+
233+
234+
@pytest.mark.unit
235+
@pytest.mark.parametrize(
236+
("recipe_factory", "tensor_model_parallel_size", "sequence_parallel"),
237+
[
238+
(nemotron_3_ultra_pretrain_256gpu_gb200_nvfp4_config, 2, True),
239+
(nemotron_3_ultra_pretrain_256gpu_gb300_nvfp4_config, 1, False),
240+
],
241+
ids=["gb200", "gb300"],
242+
)
243+
def test_nvfp4_perf_recipes_use_gtp_partial_cuda_graphs_and_nccl_ep(
244+
recipe_factory, tensor_model_parallel_size: int, sequence_parallel: bool
245+
) -> None:
246+
"""GB200 and GB300 Ultra NVFP4 shard dense weights rack-locally with GTP instead of HSDP."""
247+
cfg = recipe_factory()
248+
249+
assert cfg.model.tensor_model_parallel_size == tensor_model_parallel_size
250+
assert cfg.model.sequence_parallel is sequence_parallel
251+
assert cfg.model.expert_model_parallel_size == 64
252+
assert cfg.model.expert_tensor_parallel_size == 1
253+
assert cfg.mixed_precision.fp4 == "e2m1"
254+
assert cfg.mixed_precision.fp4_param_gather is True
255+
256+
assert cfg.dist.use_megatron_fsdp is False
257+
assert cfg.ddp.use_megatron_fsdp is False
258+
assert cfg.model.tensor_parallel_num_weight_shards == 64
259+
assert cfg.model.expert_tensor_parallel_num_weight_shards == 1
260+
assert cfg.ddp.num_distributed_optimizer_instances == 1
261+
262+
assert cfg.model.cuda_graph_impl == "local"
263+
assert cuda_graph_module_names(cfg.model) == ["attn", "mamba"]
264+
assert cfg.model.use_te_rng_tracker is True
265+
assert cfg.rng.te_rng_tracker is True
266+
267+
assert cfg.model.moe_token_dispatcher_type == "flex"
268+
assert cfg.model.moe_flex_dispatcher_backend == "ncclep"
269+
assert cfg.model.moe_use_grouped_tensor is True
270+
assert cfg.env_vars["NCCL_EP_HT_EM_PULL_PUSH"] == 1
271+
assert cfg.env_vars.keys().isdisjoint(HYBRID_EP_ENV_NAMES)
222272

223273

224274
@pytest.mark.unit

‎tests/unit_tests/recipes/test_gb300_ncclep_perf_recipes.py‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
("nemotronh.gb300.nemotronh", "nemotron_3_super_pretrain_64gpu_gb300_fp8mx_config"),
4343
("nemotronh.gb300.nemotronh", "nemotron_3_super_pretrain_64gpu_gb300_nvfp4_config"),
4444
("nemotronh.gb300.nemotronh", "nemotron_3_ultra_pretrain_256gpu_gb300_fp8mx_config"),
45+
("nemotronh.gb300.nemotronh", "nemotron_3_ultra_pretrain_256gpu_gb300_nvfp4_config"),
4546
("nemotronh.gb300.nemotronh", "nemotron_3_nano_pretrain_8gpu_gb300_bf16_config"),
4647
("nemotronh.gb300.nemotronh", "nemotron_3_nano_pretrain_8gpu_gb300_fp8mx_config"),
4748
("nemotronh.gb300.nemotronh", "nemotron_3_5_lightning_pretrain_8gpu_gb300_bf16_config"),
@@ -57,7 +58,10 @@
5758
)
5859

5960
# VRNVL72 aliases that share the GB300 NCCL EP builder instead of a HybridEP base.
60-
_VRNVL72_NCCLEP_RECIPES = (("nemotronh.vrnvl72.nemotronh", "nemotron_3_ultra_pretrain_256gpu_vrnvl72_fp8mx_config"),)
61+
_VRNVL72_NCCLEP_RECIPES = (
62+
("nemotronh.vrnvl72.nemotronh", "nemotron_3_ultra_pretrain_256gpu_vrnvl72_fp8mx_config"),
63+
("nemotronh.vrnvl72.nemotronh", "nemotron_3_ultra_pretrain_256gpu_vrnvl72_nvfp4_config"),
64+
)
6165

6266
# VRNVL72 aliases of the same recipes: they reuse the shared HybridEP builders and must not pick up NCCL EP.
6367
_VRNVL72_ALIASES = (

0 commit comments

Comments
 (0)