Skip to content

Commit 4660bc8

Browse files
committed
perf(recipes): optimize DeepSeek V4 B200 topology
Signed-off-by: Chen Cui <chcui@nvidia.com>
1 parent c5dc1a5 commit 4660bc8

4 files changed

Lines changed: 75 additions & 49 deletions

File tree

‎examples/models/deepseek_v4/README.md‎

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,10 @@ Available Blackwell pretraining recipes:
8080
- `deepseek_v4_flash_pretrain_mxfp8_config`: Adam MXFP8
8181
- `deepseek_v4_flash_pretrain_muon_config`: Muon BF16
8282
- `deepseek_v4_flash_pretrain_64gpu_b200_fp8mx_library_config`: 64-GPU B200
83-
Adam MXFP8 with PP8/VPP2/EP8, all-to-all dispatch, selective recompute, and
84-
attention activation offload plus MXFP8 parameter gather/buffer reuse
83+
Adam MXFP8 with PP4/VPP4/EP16, HybridEP across pairs of physical NVL8
84+
domains, selective `[mhc,mla_up_proj]` recompute, no activation offload, and
85+
MXFP8 parameter gather/buffer reuse. This recipe requires eight physical
86+
B200 NVL8 systems with eight contiguous, node-major ranks per system.
8587
- `deepseek_v4_flash_pretrain_128gpu_gb200_fp8mx_library_config`: 128-GPU GB200
8688
Adam MXFP8 with PP1/EP64/dense-DP128/expert-DP2/HybridEP, selective recompute,
8789
attention activation offload, and MXFP8 parameter gather/buffer reuse
@@ -101,6 +103,14 @@ TP/PP/EP/CP settings. Launch them through a site multi-node runner that invokes
101103
Keep the topology and global batch size owned by the recipe; pass only dataset,
102104
run-length, logging, and checkpoint overrides.
103105

106+
For the B200 recipe, preserve node-major global-rank assignment so each EP16
107+
group spans two physical NVL8 systems with eight ranks in each NVLink domain.
108+
Its runtime must provide an MCore-compatible HybridEP package exposing
109+
`deep_ep.HybridEPBuffer` with cross-domain DMA-BUF registration and completion
110+
notification support. The site launcher must also provide the topology-correct
111+
NIC mapping required by that package. Megatron Bridge's `uv sync` does not
112+
install or configure this external runtime.
113+
104114
The GB200 Flash and GB300 Pro library bases enable their supported DSA and
105115
Transformer Engine fused grouped-MLP paths. The new hardware-count-specific
106116
variants additionally enable GLU interleaving; the existing recipe identities
@@ -109,8 +119,9 @@ natural-routing capacity. All variants retain their precision-specific
109119
training policies: full-iteration CUDA graphs, FP8 parameter gather/buffer
110120
reuse, and reduced-precision gradient reduction remain disabled except for the
111121
provisional FP8 parameter gather/buffer reuse in the high-scale B200 and GB200
112-
Flash recipes; both configurations still require 100-step checkpoint and resume
113-
validation.
122+
Flash recipes. These configurations require 100-step natural-routing training,
123+
full model/optimizer/RNG checkpoint save, and fresh-process resume validation on
124+
the documented Megatron-LM `dev` stack.
114125

115126
`slurm_pretrain.sh` is a GB200 launcher with `TP=1,PP=4,EP=8,CP=1` by default. Indexer loss are disabled for now and is planned for a follow-up.
116127

‎src/megatron/bridge/recipes/deepseek/b200/deepseek_v4.py‎

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -19,51 +19,53 @@
1919
from megatron.bridge.training.config import ConfigContainer
2020

2121

22-
_DSV4_FLASH_PP8_VP2_LAYOUT = "Et*3|t*3|t*3|t*3|t*3|t*3|t*3|t*3|t*3|t*3|t*3|t*2|t*2|t*2|t*2|t*2mL"
23-
_FLEX_DISPATCHER_ENV_VARS = {
24-
"NUM_OF_HYBRID_EP_RANKS_PER_NVLINK_DOMAIN",
25-
"NUM_OF_TOKENS_PER_CHUNK_COMBINE_API",
26-
"NVLINK_DOMAIN_SIZE",
27-
"USE_MNNVL",
28-
}
22+
_DSV4_FLASH_PP4_VP4_LAYOUT = "Et*3|t*3|t*3|t*3|t*3|t*3|t*3|t*3|t*3|t*3|t*3|t*2|t*2|t*2|t*2|t*2mL"
2923

3024

3125
def deepseek_v4_flash_pretrain_64gpu_b200_fp8mx_library_config() -> ConfigContainer:
3226
"""Return real-training DeepSeek V4 Flash for 64 B200 GPUs.
3327
34-
PP8/VPP2 keeps each eight-rank expert group within one NVL8 system. The
35-
recipe uses the portable all-to-all dispatcher and preserves natural,
36-
unlimited-capacity routing without paged stash or CUDA graphs.
28+
Requires eight physical NVL8 systems with eight contiguous, node-major
29+
ranks per system. Each EP16 group spans two NVL8 domains, with eight ranks
30+
per domain. The runtime must expose ``deep_ep.HybridEPBuffer``. Natural,
31+
unlimited-capacity routing is preserved without paged stash, activation
32+
offload, or CUDA graphs.
3733
"""
3834
cfg = deepseek_v4_flash_pretrain_128gpu_gb200_fp8mx_library_config()
3935

4036
cfg.model.tensor_model_parallel_size = 1
41-
cfg.model.pipeline_model_parallel_size = 8
42-
cfg.model.virtual_pipeline_model_parallel_size = 2
37+
cfg.model.pipeline_model_parallel_size = 4
38+
cfg.model.virtual_pipeline_model_parallel_size = 4
4339
cfg.model.context_parallel_size = 1
44-
cfg.model.expert_model_parallel_size = 8
40+
cfg.model.expert_model_parallel_size = 16
4541
cfg.model.expert_tensor_parallel_size = 1
4642
cfg.model.sequence_parallel = False
47-
cfg.model.pipeline_model_parallel_layout = _DSV4_FLASH_PP8_VP2_LAYOUT
43+
cfg.model.pipeline_model_parallel_layout = _DSV4_FLASH_PP4_VP4_LAYOUT
4844

49-
cfg.model.moe_token_dispatcher_type = "alltoall"
50-
cfg.model.moe_flex_dispatcher_backend = None
51-
cfg.model.moe_flex_dispatcher_num_sms = None
45+
cfg.model.moe_token_dispatcher_type = "flex"
46+
cfg.model.moe_flex_dispatcher_backend = "hybridep"
47+
cfg.model.moe_flex_dispatcher_num_sms = 32
5248
cfg.model.moe_deepep_num_sms = None
5349
cfg.model.moe_hybridep_num_sms = None
54-
cfg.model.moe_hybridep_num_sms_preprocessing = None
50+
cfg.model.moe_hybridep_num_sms_preprocessing = 108
5551
cfg.model.moe_shared_expert_overlap = False
5652

57-
cfg.model.recompute_modules = ["moe", "mhc", "mla_up_proj", "layernorm"]
58-
cfg.model.fine_grained_activation_offloading = True
59-
cfg.model.offload_modules = ["core_attn", "attn_proj"]
60-
cfg.model.fine_grained_offloading_max_inflight_offloads = 2
53+
cfg.model.recompute_modules = ["mhc", "mla_up_proj"]
54+
cfg.model.fine_grained_activation_offloading = False
55+
cfg.model.offload_modules = []
56+
cfg.model.fine_grained_offloading_max_inflight_offloads = None
6157
cfg.model.moe_pad_experts_for_cuda_graph_inference = False
6258
cfg.model.cuda_graph_impl = "none"
6359
cfg.model.cuda_graph_modules = []
6460
cfg.model.cuda_graph_scope = None
6561
cfg.model.use_te_rng_tracker = False
6662
cfg.rng.te_rng_tracker = False
6763

68-
cfg.env_vars = {key: value for key, value in cfg.env_vars.items() if key not in _FLEX_DISPATCHER_ENV_VARS}
64+
cfg.env_vars = {
65+
**{key: value for key, value in cfg.env_vars.items() if key != "NVTE_CPU_OFFLOAD_V1"},
66+
"NUM_OF_HYBRID_EP_RANKS_PER_NVLINK_DOMAIN": 8,
67+
"NUM_OF_TOKENS_PER_CHUNK_COMBINE_API": 128,
68+
"NVLINK_DOMAIN_SIZE": 8,
69+
"USE_MNNVL": 0,
70+
}
6971
return cfg

‎src/megatron/bridge/recipes/deepseek/gb200/deepseek_v4.py‎

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,6 @@ def deepseek_v4_flash_pretrain_64gpu_gb200_bf16_config() -> ConfigContainer:
4444
All features validated in 1k-step convergence runs on OCI GB200 NVL72:
4545
fused DSA indexer, DSA indexer loss, HybridEP dispatcher, GroupedGEMM,
4646
permute fusion, selective recompute with mla_up_proj.
47-
48-
Note: set checkpoint.save_optim=False when using HybridEP.
4947
"""
5048
use_fused_mhc = deepseek_v4_supports_blackwell_fused_kernels()
5149
cfg = _pretrain_common()
@@ -145,10 +143,7 @@ def deepseek_v4_flash_pretrain_64gpu_gb200_bf16_config() -> ConfigContainer:
145143

146144

147145
def deepseek_v4_flash_pretrain_64gpu_gb200_fp8mx_config() -> ConfigContainer:
148-
"""DeepSeek-V4-Flash MXFP8 pre-training on 64-GPU GB200 (PP=8, EP=8).
149-
150-
Note: set checkpoint.save_optim=False when using HybridEP.
151-
"""
146+
"""DeepSeek-V4-Flash MXFP8 pre-training on 64-GPU GB200 (PP=8, EP=8)."""
152147
cfg = deepseek_v4_flash_pretrain_64gpu_gb200_bf16_config()
153148

154149
cfg.model.dsa_indexer_loss_coeff = 0.0

‎tests/unit_tests/recipes/test_deepseek_v4_hardware_recipes.py‎

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,10 @@ def test_flash_high_scale_recipe_preserves_real_training_contract() -> None:
175175
assert cfg.ddp.grad_reduce_in_fp32 is True
176176
assert cfg.optimizer.main_grads_dtype == torch.float32
177177
assert cfg.ddp.check_for_nan_in_grad is True
178+
assert cfg.checkpoint.save_optim is True
179+
assert cfg.checkpoint.save_rng is True
180+
assert cfg.checkpoint.load_optim is True
181+
assert cfg.checkpoint.load_rng is True
178182
assert cfg.model.cuda_graph_impl == "none"
179183
assert cfg.model.use_transformer_engine_op_fuser is True
180184
assert cfg.model.moe_mlp_glu_interleave_size == 32
@@ -198,9 +202,9 @@ def test_flash_b200_nvl8_recipe_preserves_real_training_contract() -> None:
198202
assert cfg.train.train_iters == 1_000_000
199203
assert cfg.train.global_batch_size == 256
200204
assert cfg.model.tensor_model_parallel_size == 1
201-
assert cfg.model.pipeline_model_parallel_size == 8
202-
assert cfg.model.virtual_pipeline_model_parallel_size == 2
203-
assert cfg.model.expert_model_parallel_size == 8
205+
assert cfg.model.pipeline_model_parallel_size == 4
206+
assert cfg.model.virtual_pipeline_model_parallel_size == 4
207+
assert cfg.model.expert_model_parallel_size == 16
204208
assert cfg.model.pipeline_model_parallel_layout == (
205209
"Et*3|t*3|t*3|t*3|t*3|t*3|t*3|t*3|t*3|t*3|t*3|t*2|t*2|t*2|t*2|t*2mL"
206210
)
@@ -209,29 +213,43 @@ def test_flash_b200_nvl8_recipe_preserves_real_training_contract() -> None:
209213
pipeline_model_parallel_size=cfg.model.pipeline_model_parallel_size,
210214
)
211215
parsed_layout.validate_layer_layout(num_layers=43, mtp_num_layers=1)
212-
assert parsed_layout.virtual_pipeline_model_parallel_size == 2
213-
assert cfg.model.moe_token_dispatcher_type == "alltoall"
214-
assert cfg.model.moe_flex_dispatcher_backend is None
215-
assert cfg.model.moe_flex_dispatcher_num_sms is None
216+
assert parsed_layout.virtual_pipeline_model_parallel_size == 4
217+
assert cfg.model.moe_token_dispatcher_type == "flex"
218+
assert cfg.model.moe_flex_dispatcher_backend == "hybridep"
219+
assert cfg.model.moe_flex_dispatcher_num_sms == 32
220+
assert cfg.model.moe_deepep_num_sms is None
221+
assert cfg.model.moe_hybridep_num_sms is None
222+
assert cfg.model.moe_hybridep_num_sms_preprocessing == 108
223+
assert cfg.model.moe_shared_expert_overlap is False
216224
assert cfg.model.moe_router_force_load_balancing is False
217-
assert cfg.model.recompute_modules == ["moe", "mhc", "mla_up_proj", "layernorm"]
218-
assert cfg.model.fine_grained_activation_offloading is True
219-
assert cfg.model.offload_modules == ["core_attn", "attn_proj"]
220-
assert cfg.model.fine_grained_offloading_max_inflight_offloads == 2
225+
assert getattr(cfg.model, "moe_router_force_biased", None) is None
226+
assert getattr(cfg.model, "moe_expert_capacity_factor", None) is None
227+
assert cfg.model.recompute_modules == ["mhc", "mla_up_proj"]
228+
assert cfg.model.recompute_granularity == "selective"
229+
assert cfg.model.recompute_method is None
230+
assert cfg.model.recompute_num_layers is None
231+
assert cfg.model.fine_grained_activation_offloading is False
232+
assert cfg.model.offload_modules == []
233+
assert cfg.model.fine_grained_offloading_max_inflight_offloads is None
221234
assert cfg.mixed_precision.fp8_param_gather is True
222235
assert cfg.mixed_precision.reuse_grad_buf_for_mxfp8_param_ag is True
223236
assert getattr(cfg.model, "moe_expert_rank_capacity_factor", None) is None
237+
assert getattr(cfg.model, "moe_token_dropping", False) is False
224238
assert getattr(cfg.model, "moe_paged_stash", False) is False
225239
assert cfg.model.cuda_graph_impl == "none"
226240
assert cfg.model.cuda_graph_modules == []
227241
assert cfg.model.cuda_graph_scope is None
228242
assert cfg.rerun_state_machine.check_for_nan_in_loss is True
229243
assert cfg.ddp.check_for_nan_in_grad is True
230-
assert "NUM_OF_HYBRID_EP_RANKS_PER_NVLINK_DOMAIN" not in cfg.env_vars
231-
assert "NUM_OF_TOKENS_PER_CHUNK_COMBINE_API" not in cfg.env_vars
232-
assert "NVLINK_DOMAIN_SIZE" not in cfg.env_vars
233-
assert "USE_MNNVL" not in cfg.env_vars
234-
assert cfg.env_vars["NVTE_CPU_OFFLOAD_V1"] == 1
244+
assert cfg.checkpoint.save_optim is True
245+
assert cfg.checkpoint.save_rng is True
246+
assert cfg.checkpoint.load_optim is True
247+
assert cfg.checkpoint.load_rng is True
248+
assert cfg.env_vars["NUM_OF_HYBRID_EP_RANKS_PER_NVLINK_DOMAIN"] == 8
249+
assert cfg.env_vars["NUM_OF_TOKENS_PER_CHUNK_COMBINE_API"] == 128
250+
assert cfg.env_vars["NVLINK_DOMAIN_SIZE"] == 8
251+
assert cfg.env_vars["USE_MNNVL"] == 0
252+
assert "NVTE_CPU_OFFLOAD_V1" not in cfg.env_vars
235253

236254

237255
def test_pro_high_scale_recipe_preserves_real_training_contract() -> None:

0 commit comments

Comments
 (0)