Skip to content

Commit 1673533

Browse files
fix(ckpt): disable shared-expert overlap in single-rank flex fallback (#6287)
Signed-off-by: Kamran Jafari <kjafarisadeg@nvidia.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 6ba4afb commit 1673533

2 files changed

Lines changed: 35 additions & 1 deletion

File tree

‎src/megatron/bridge/training/model_load_save.py‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -537,12 +537,14 @@ def load_megatron_model(
537537
if model_cfg.pipeline_model_parallel_size == 1 and model_cfg.virtual_pipeline_model_parallel_size is None:
538538
model_cfg.pipeline_model_parallel_layout = None
539539

540-
# Flex dispatcher requires TPxEP > 1; fall back to allgather for single-rank export
540+
# DeepEP and NCCL EP flex backends require TPxEP > 1, so single-rank loads fall back to allgather.
541+
# MCore allows shared-expert overlap only with alltoall and flex, so disable it with the fallback.
541542
if getattr(model_cfg, "moe_token_dispatcher_type", None) == "flex":
542543
tp = getattr(model_cfg, "tensor_model_parallel_size", 1)
543544
ep = getattr(model_cfg, "expert_model_parallel_size", 1)
544545
if tp * ep == 1:
545546
model_cfg.moe_token_dispatcher_type = "allgather"
547+
model_cfg.moe_shared_expert_overlap = False
546548

547549
return build_and_load_model(
548550
checkpoint_path, model_cfg, model_type, mlm_args, return_state_dict, use_cpu_init, skip_temp_dist_context

‎tests/unit_tests/training/test_model_load_save.py‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,38 @@ def test_explicit_dropless_load_preserves_hybridep(
450450
assert built_config.moe_router_force_load_balancing is (not dropless)
451451
assert built_config.moe_router_force_biased == (None if dropless else forced_bias)
452452

453+
@pytest.mark.parametrize(
454+
("expert_parallel_size", "expected_dispatcher", "expected_overlap"),
455+
[(1, "allgather", False), (2, "flex", True)],
456+
)
457+
def test_single_rank_flex_fallback_disables_shared_expert_overlap(
458+
self, expert_parallel_size, expected_dispatcher, expected_overlap
459+
):
460+
"""Single-rank loads replace flex with allgather, which does not support shared-expert overlap."""
461+
provider = GPTModelProvider(
462+
num_layers=2,
463+
hidden_size=16,
464+
num_attention_heads=2,
465+
num_moe_experts=2,
466+
moe_shared_expert_intermediate_size=16,
467+
moe_shared_expert_overlap=True,
468+
moe_token_dispatcher_type="flex",
469+
moe_flex_dispatcher_backend="hybridep",
470+
)
471+
472+
def finalize_before_build(checkpoint_path, model_cfg, *args, **build_kwargs):
473+
model_cfg.finalize()
474+
return []
475+
476+
with (
477+
patch.object(model_load_save, "load_model_config", return_value=(provider, None)),
478+
patch.object(model_load_save, "build_and_load_model", side_effect=finalize_before_build),
479+
):
480+
load_megatron_model("/checkpoint", mp_overrides={"expert_model_parallel_size": expert_parallel_size})
481+
482+
assert provider.moe_token_dispatcher_type == expected_dispatcher
483+
assert provider.moe_shared_expert_overlap is expected_overlap
484+
453485
def test_load_model_config_preserves_finalized_pipeline_layout(self, tmp_path):
454486
"""Verify native checkpoints retain a finalized custom pipeline layout."""
455487
provider = GPTModelProvider(num_layers=2, hidden_size=16, num_attention_heads=2)

0 commit comments

Comments
 (0)