Skip to content

feat(fsdp): expose HSDP and HFSDP through the MFSDP v2 adapter - #6873

Merged
wujingyue merged 11 commits into
NVIDIA:mainfrom
wujingyue:agent/mfsdp-v2-hsdp
Aug 31, 2026
Merged

wujingyue merged 11 commits into
NVIDIA:mainfrom
wujingyue:agent/mfsdp-v2-hsdp

Conversation

@wujingyue

@wujingyue wujingyue commented Aug 26, 2026 •

Copy link
Copy Markdown
Contributor

Summary

MFSDP v2's core already supports hybrid sharding, but the MCore adapter never built a
second data-parallel axis: num_distributed_optimizer_instances was ignored and every
parameter was sharded over the full DP domain. This wires it up.

Dense parameters take a ("dp_outer", "dp_shard") mesh whenever there is more than one
instance. Expert parameters deliberately do not — they stay ZeRO-3 over the whole
expert-DP domain, since sharding the large parameters maximally is worth more than the
intra-instance collectives hybrid sharding buys.

No HSDP/HFSDP special case

Each axis takes the placements of its own sharding strategy, per
mfsdp_design.md:

strategy parameter gradient optimizer
no_shard replicate partial replicate DDP
optim replicate partial shard ZeRO-1
optim_grads replicate shard shard ZeRO-2
optim_grads_params shard shard shard ZeRO-3

So HSDP is no_shard outer over ZeRO-3 inner, and HFSDP is ZeRO-1 outer over ZeRO-3
inner — whose optimizer is then sharded on both axes, i.e. across the flattened DP
domain. ZeRO-2 and ZeRO-3 on the outer axis come for free.

num_distributed_optimizer_instances decides only whether an outer axis exists;
outer_dp_sharding_strategy decides what lives on it. Both strategy fields are now
validated in DistributedDataParallelConfig.__post_init__ rather than deep in the FSDP
code, since the names are config vocabulary.

Validation

On 4 GPUs, TestMcoreAdapterHybrid — 5 passed:

  • placements are (Replicate, Shard(0)) for HSDP and (Shard(0), Shard(0)) for HFSDP,
    on a ("dp_outer", "dp_shard") mesh
  • both produce the same losses over three steps as a single data-parallel instance,
    so splitting the domain leaves the math unchanged
  • MoE with EP=2 and two instances puts dense parameters on the hybrid mesh and experts
    on ("expert_dp",), and nothing else — experts never acquire an outer axis

test_mcore_adapter.py is 11 passed; with test_param_and_grad_buffer.py, 108 passed /
4 skipped, since the new config validation runs on every DistributedDataParallelConfig.

🤖 Generated with Claude Code

@copy-pr-bot

copy-pr-bot Bot commented Aug 26, 2026

Copy link
Copy Markdown

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

Comment thread megatron/core/distributed/fsdp/mcore_fsdp_adapter.py Outdated
Comment thread tests/unit_tests/distributed/mfsdp_v2/test_mcore_adapter.py Outdated
Comment thread megatron/core/distributed/fsdp/mcore_fsdp_adapter.py Outdated
Comment thread megatron/core/distributed/fsdp/mcore_fsdp_adapter.py Outdated
@wujingyue
wujingyue marked this pull request as ready for review August 26, 2026 04:53
@wujingyue
wujingyue requested review from a team as code owners August 26, 2026 04:53
@wujingyue

Copy link
Copy Markdown
Contributor Author

/ok to test

)

inner_size = inner_group.size()
layout = torch.arange(dist.get_world_size()).reshape(outer_group.size(), inner_size).tolist()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’m a bit confused🤔: why can we use the get_world_size() to compute the expected indexs? Are we assuming that world_size = inner_dp × outer_dp?
It would be helpful to understand how this work when TP, PP, or EP(maybe with #6798) is also present, or whether support for those configurations is outside the current scope.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the assumption is world_size == outer_dp × inner_dp. This mirrors v1: _get_hsdp_tp_mesh (:864) also reshapes torch.arange(world_size) (:869), just with extra ep/tp factors that reduce away when those are 1.

It's checked rather than assumed — this rank's row is compared against intra_dp_cp and its column against inter_dist_opt (:845, :850), so a mismatch raises instead of silently mis-mapping shards. TP/PP/CP above 1 are rejected in _validate_config (:658), so a config that would break the identity can't reach here.

@copy-pr-bot

copy-pr-bot Bot commented Aug 26, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@wujingyue
wujingyue force-pushed the agent/mfsdp-v2-hsdp branch from ce2b895 to 3ed254e Compare August 26, 2026 20:54
@wujingyue

Copy link
Copy Markdown
Contributor Author

/ok to test

@wujingyue

Copy link
Copy Markdown
Contributor Author

/ok to test

Signed-off-by: Jingyue Wu <jingyuew@nvidia.com>
Signed-off-by: Jingyue Wu <jingyuew@nvidia.com>
Signed-off-by: Jingyue Wu <jingyuew@nvidia.com>
@svcnvidia-nemo-ci svcnvidia-nemo-ci added the Approved All necessary approvals have been made label Aug 30, 2026
@wujingyue
wujingyue removed request for a team August 30, 2026 15:16
@wujingyue
wujingyue added this pull request to the merge queue Aug 31, 2026
@nemo-automation-bot

Copy link
Copy Markdown

🔄 Merge queue validation started!

You can track the progress here: https://github.com/NVIDIA/Megatron-LM/actions/runs/33345851729

Merged via the queue into NVIDIA:main with commit 713ea6a Aug 31, 2026
201 checks passed
@wujingyue
wujingyue deleted the agent/mfsdp-v2-hsdp branch August 31, 2026 02:32
wujingyue added a commit to wujingyue/Megatron-Bridge that referenced this pull request Sep 1, 2026
…ware optimizer, HSDP, and optimizer CUDA graphs

Megatron-LM landed dedicated MFSDP v2 support for these, each with its own commits and
tests, after this validation function was written:

- clip_grad: MFSDP v2 gradient clipping across dense and expert meshes (NVIDIA/Megatron-LM#6489)
- use_precision_aware_optimizer: mixed-precision optimizers in MFSDP v2 (NVIDIA/Megatron-LM#6506)
- num_distributed_optimizer_instances / outer_dp_sharding_strategy (HSDP): expose HSDP and
  HFSDP through the MFSDP v2 adapter (NVIDIA/Megatron-LM#6873); the adapter itself now enforces
  the correct paired constraint, so no replacement check is needed here
- optimizer_cuda_graph: verified for MFSDP v2 (NVIDIA/Megatron-LM#6498)

Verified end-to-end against Megatron-LM main + Megatron-Bridge with the DeepSeek-V3 MFSDP
v2 + EP proxy config (clip_grad=1.0): 20/20 iterations, finite decreasing loss, no skipped
or NaN iterations.
wujingyue added a commit to wujingyue/Megatron-Bridge that referenced this pull request Sep 1, 2026
…ware optimizer, HSDP, and optimizer CUDA graphs

Megatron-LM landed dedicated MFSDP v2 support for these, each with its own commits and
tests, after this validation function was written:

- clip_grad: MFSDP v2 gradient clipping across dense and expert meshes (NVIDIA/Megatron-LM#6489)
- use_precision_aware_optimizer: mixed-precision optimizers in MFSDP v2 (NVIDIA/Megatron-LM#6506)
- num_distributed_optimizer_instances / outer_dp_sharding_strategy (HSDP): expose HSDP and
  HFSDP through the MFSDP v2 adapter (NVIDIA/Megatron-LM#6873); the adapter itself now enforces
  the correct paired constraint, so no replacement check is needed here
- optimizer_cuda_graph: verified for MFSDP v2 (NVIDIA/Megatron-LM#6498)

Verified end-to-end against Megatron-LM main + Megatron-Bridge with the DeepSeek-V3 MFSDP
v2 + EP proxy config (clip_grad=1.0): 20/20 iterations, finite decreasing loss, no skipped
or NaN iterations.

Signed-off-by: Jingyue Wu <wujingyue@gmail.com>
ksivaman pushed a commit to ksivaman/Megatron-LM that referenced this pull request Sep 1, 2026
wujingyue added a commit to wujingyue/Megatron-Bridge that referenced this pull request Sep 11, 2026
…ware optimizer, HSDP, and optimizer CUDA graphs

Megatron-LM landed dedicated MFSDP v2 support for these, each with its own commits and
tests, after this validation function was written:

- clip_grad: MFSDP v2 gradient clipping across dense and expert meshes (NVIDIA/Megatron-LM#6489)
- use_precision_aware_optimizer: mixed-precision optimizers in MFSDP v2 (NVIDIA/Megatron-LM#6506)
- num_distributed_optimizer_instances / outer_dp_sharding_strategy (HSDP): expose HSDP and
  HFSDP through the MFSDP v2 adapter (NVIDIA/Megatron-LM#6873); the adapter itself now enforces
  the correct paired constraint, so no replacement check is needed here
- optimizer_cuda_graph: verified for MFSDP v2 (NVIDIA/Megatron-LM#6498)

Verified end-to-end against Megatron-LM main + Megatron-Bridge with the DeepSeek-V3 MFSDP
v2 + EP proxy config (clip_grad=1.0): 20/20 iterations, finite decreasing loss, no skipped
or NaN iterations.

Signed-off-by: Jingyue Wu <wujingyue@gmail.com>

This branch was previously deployed

2 inactive deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Approved All necessary approvals have been made complexity: medium Run tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

mFSDP v2 should support heterogeneous FSDP configurations for different parameter groups. MFSDP v2 should support HSDP and HFSDP placements

3 participants