|
57 | 57 | nemotron_3_nano_pretrain_16gpu_h100_fp8cs_config, |
58 | 58 | ) |
59 | 59 | from megatron.bridge.training.config import ConfigContainer |
| 60 | +from megatron.bridge.utils.cuda_graph import cuda_graph_module_names, is_full_iteration_cuda_graph |
60 | 61 |
|
61 | 62 |
|
62 | 63 | pytestmark = pytest.mark.unit |
|
107 | 108 | nemotron_3_5_lightning_pretrain_8gpu_gb200_fp8mx_fsdp_config, |
108 | 109 | nemotron_3_5_lightning_pretrain_8gpu_gb300_fp8mx_fsdp_config, |
109 | 110 | ) |
| 111 | +_FULL_ITERATION_MXFP8_RECIPES = ( |
| 112 | + nemotron_3_5_lightning_pretrain_8gpu_gb300_fp8mx_config, |
| 113 | + nemotron_3_5_lightning_pretrain_8gpu_vr200_fp8mx_config, |
| 114 | +) |
110 | 115 | _VR200_RECIPES = ( |
111 | 116 | nemotron_3_5_lightning_pretrain_8gpu_vr200_bf16_config, |
112 | 117 | nemotron_3_5_lightning_pretrain_8gpu_vr200_fp8mx_config, |
@@ -344,6 +349,12 @@ def test_nemotron_3_5_perf_recipes_inherit_nemotron_3_policy( |
344 | 349 |
|
345 | 350 | if recipe_factory in _B_MXFP8_RECIPES: |
346 | 351 | assert cfg.env_vars == {**base_cfg.env_vars, "NVTE_CUTEDSL_FUSED_GROUPED_MLP": 1} |
| 352 | + elif recipe_factory in _FULL_ITERATION_MXFP8_RECIPES: |
| 353 | + assert cfg.env_vars == { |
| 354 | + **base_cfg.env_vars, |
| 355 | + "PYTORCH_CUDA_ALLOC_CONF": "expandable_segments:True,graph_capture_record_stream_reuse:True", |
| 356 | + "TORCH_NCCL_AVOID_RECORD_STREAMS": 0, |
| 357 | + } |
347 | 358 | elif recipe_factory is not nemotron_3_5_lightning_pretrain_16gpu_h100_bf16_config: |
348 | 359 | assert cfg.env_vars == base_cfg.env_vars |
349 | 360 | assert cfg.model.calculate_per_token_loss == base_cfg.model.calculate_per_token_loss |
@@ -394,6 +405,41 @@ def test_gb_mxfp8_enables_cutedsl_fusion(recipe_factory: Callable[[], ConfigCont |
394 | 405 | assert cfg.comm_overlap.delay_wgrad_compute is False |
395 | 406 |
|
396 | 407 |
|
| 408 | +@pytest.mark.parametrize("recipe_factory", _FULL_ITERATION_MXFP8_RECIPES, ids=lambda recipe: recipe.__name__) |
| 409 | +def test_mxfp8_full_iteration_graph_config(recipe_factory: Callable[[], ConfigContainer]) -> None: |
| 410 | + """Lightning full-iteration recipes satisfy graph and static MoE buffer constraints.""" |
| 411 | + cfg = recipe_factory() |
| 412 | + |
| 413 | + assert cfg.model.cuda_graph_impl == "full_iteration" |
| 414 | + assert cfg.model.cuda_graph_scope is None |
| 415 | + assert cfg.model.cuda_graph_modules == [] |
| 416 | + assert is_full_iteration_cuda_graph(cfg.model) |
| 417 | + assert cfg.model.use_te_rng_tracker is True |
| 418 | + assert cfg.rng.te_rng_tracker is True |
| 419 | + assert cfg.rerun_state_machine.check_for_nan_in_loss is False |
| 420 | + assert cfg.ddp.check_for_nan_in_grad is False |
| 421 | + assert cfg.model.recompute_granularity is None |
| 422 | + assert cfg.model.offload_modules == [] |
| 423 | + assert cfg.model.moe_expert_rank_capacity_factor == 1.5 |
| 424 | + assert cfg.model.moe_use_grouped_tensor is True |
| 425 | + assert cfg.model.moe_paged_stash is False |
| 426 | + assert cfg.env_vars["TORCH_NCCL_AVOID_RECORD_STREAMS"] == 0 |
| 427 | + assert "graph_capture_record_stream_reuse:True" in cfg.env_vars["PYTORCH_CUDA_ALLOC_CONF"] |
| 428 | + assert cfg.env_vars["NVTE_CUTEDSL_FUSED_GROUPED_MLP"] == 1 |
| 429 | + assert cfg.env_vars["CUDNNFE_CLUSTER_OVERLAP_MARGIN"] == 8 |
| 430 | + assert cfg.model.use_transformer_engine_op_fuser is True |
| 431 | + assert cfg.model.moe_mlp_glu_interleave_size is None |
| 432 | + assert cfg.model.high_priority_a2a_comm_stream is False |
| 433 | + assert cfg.model.moe_hybridep_num_sms_preprocessing == 108 |
| 434 | + assert cfg.mixed_precision.fp8_dot_product_attention is True |
| 435 | + assert cfg.comm_overlap.overlap_moe_expert_parallel_comm is False |
| 436 | + assert cfg.comm_overlap.delay_wgrad_compute is False |
| 437 | + |
| 438 | + # Validate against MCore as well as checking the unfinalized recipe settings. |
| 439 | + cfg.model.finalize() |
| 440 | + assert is_full_iteration_cuda_graph(cfg.model) |
| 441 | + |
| 442 | + |
397 | 443 | @pytest.mark.parametrize("recipe_factory", _GB_FSDP_RECIPES, ids=lambda recipe: recipe.__name__) |
398 | 444 | def test_gb_mxfp8_fsdp_skips_cutedsl_fusion(recipe_factory: Callable[[], ConfigContainer]) -> None: |
399 | 445 | """The Lightning GB MXFP8 FSDP variants remain outside the CutDSL tuning scope.""" |
@@ -542,6 +588,14 @@ def test_gb200_perf_recipe_topology(recipe_factory: Callable[[], ConfigContainer |
542 | 588 | assert cfg.env_vars["NVLINK_DOMAIN_SIZE"] == 72 |
543 | 589 | assert cfg.env_vars["USE_MNNVL"] == 1 |
544 | 590 |
|
| 591 | + if recipe_factory is nemotron_3_5_lightning_pretrain_8gpu_gb200_fp8mx_config: |
| 592 | + assert cfg.model.cuda_graph_impl == "transformer_engine" |
| 593 | + assert cuda_graph_module_names(cfg.model) == ["attn", "mamba", "moe_router", "moe_preprocess"] |
| 594 | + assert cfg.model.moe_expert_rank_capacity_factor is None |
| 595 | + assert cfg.model.moe_paged_stash is False |
| 596 | + assert cfg.env_vars["PYTORCH_CUDA_ALLOC_CONF"] == "expandable_segments:True" |
| 597 | + assert cfg.env_vars["TORCH_NCCL_AVOID_RECORD_STREAMS"] == 1 |
| 598 | + |
545 | 599 |
|
546 | 600 | @pytest.mark.parametrize("recipe_factory", _GB300_RECIPES, ids=lambda recipe: recipe.__name__) |
547 | 601 | def test_gb300_perf_recipe_topology(recipe_factory: Callable[[], ConfigContainer]) -> None: |
@@ -619,6 +673,8 @@ def test_gb_fsdp_perf_recipe_defaults(recipe_factory: Callable[[], ConfigContain |
619 | 673 | assert cfg.model.cuda_graph_impl == "none" |
620 | 674 | assert cfg.model.cuda_graph_scope is None |
621 | 675 | assert cfg.model.cuda_graph_modules == [] |
| 676 | + assert cfg.model.moe_expert_rank_capacity_factor is None |
| 677 | + assert cfg.model.moe_paged_stash is False |
622 | 678 | assert cfg.model.init_model_with_meta_device is True |
623 | 679 |
|
624 | 680 | assert cfg.mixed_precision.reuse_grad_buf_for_mxfp8_param_ag is False |
|
0 commit comments