fix(distributed): control frozen multimodal FSDP sharding - #2763
Conversation
|
/ok to test 217af2b |
|
Triggered scoped real GPU CI for correctness on the current PR head:
This is correctness-only. I still consider the performance question WIP until we run more controlled paired benchmarks. |
|
Scoped real GPU CI passed for the current PR head.
Passed jobs:
This was correctness coverage only; I am not treating this as a performance conclusion for |
|
@yuhezhang-ai that's awesome; i found the mistral recipe 62a9898#diff-c5a488bfa4afe12e07697c2c0e708633517dcee3a2da8ff14b0d6f491b4123f0R147 to be affected by this, would it be ok to include it in the testing? 🙏 -- I'd very much revert 2744 and keep this. Thank you for jumping on this right away! |
|
Thank you @yuhezhang-ai , can we also make sure convergence is not impacted by this. Ideally it shouldn't. If you like I can help check for gemma4s whenever the PR is ready, lmk |
|
Added Alex's requested Mistral coverage. Scoped real GPU CI passed for
Note: this recipe is a text-only LLM recipe that loads the Mistral3 FP8 VLM wrapper. Its vision tower is skipped by the data path but is not explicitly frozen by the recipe, so this validates that the current default behavior plus the existing FSDP accumulated-grad guard still works. The new |
|
While this PR is trying to add a opt in knob to replicate the frozen vision/audio tower, I found a bigger inconsistency in how we treat multimodal tower. See details below: The issue is not really frozen vs trainable. It is whether a separately wrapped vision/audio FSDP unit actually runs for a batch. If a batch skips that modality, the tower’s FSDP forward hook may never run, so PyTorch may not create Today we effectively have two ways to avoid the problem:
The code currently uses both approaches inconsistently. MoE root-shards frozen audio/visual towers. Dense VLMs often per-layer shard frozen vision through the generic layer policy, while frozen audio has special root-shard handling. Proposed direction:
Risk: this relies on a narrow monkey patch against private PyTorch FSDP2 internals. The patch only handles the case where This would remove the dense/MoE inconsistency and expose only the real user choice: shard frozen multimodal params or replicate them. |
|
Follow-up after looking more closely at the rank-asymmetric mixed-media case: I think the proposed direction above should change slightly. This proposal is scoped to fully frozen multimodal towers; trainable conditional towers are a separate problem and are out of scope for this PR. The accumulated-grad guard from #2744 and root sharding solve two different failures:
For fully frozen towers, I think the user-facing policy should expose three explicit choices: frozen_multimodal_sharding: root # default, correctness-first
# frozen_multimodal_sharding: per_layer # expert opt-in
# frozen_multimodal_sharding: replicate # full copy on each rankProposed semantics:
This intentionally changes the default topology for dense frozen vision, which is generally per-layer sharded today. Frozen audio and MoE frozen towers are already root-owned in the common paths, so making
The For coverage, I suggest:
|
|
Follow-up audit and measurements for the proposed Decision: keep Retained-config benchmarkI ran the tracked
* excluding steps 0-1. The complete 15-step train-loss sequence and validation loss were identical across policies. Relative to I also completed a supplemental Qwen2.5-VL 3B matrix before noting that config is slated for deprecation; it reached Config audit
The only two VLM-labeled configs with Regression coverageA real two-rank FSDP2 regression now passes (job
Focused unit coverage is also green: |
5c680f3 to
06f6df9
Compare
Signed-off-by: Yuhe Zhang <yuhez@nvidia.com>
06f6df9 to
3600856
Compare
|
Post-rebase audit and benchmark update for Decision: keep Current-config measurementsAll runs below used the rebased signed head
The two Qwen3 8-GPU run means together give +2.65% for replication. The earlier retained Gemma4 E4B matrix measured Gemma3 and both Gemma4 matrices produced identical train-loss sequences across policies. Gemma4 MoE Jobs: Post-rebase config audit
Regression and validation
|
|
/ok to test 3600856 |
Signed-off-by: Yuhe Zhang <yuhez@nvidia.com>
Signed-off-by: Yuhe Zhang <yuhez@nvidia.com>
|
/ok to test dd7a867 |
|
Important: This PR was assigned to me on 7/27 and was merged on 7/28 before the technical publications review of the markdown files could be completed. Please note that I require a 48-hour window to review PRs, and a review of all customer-facing content is a mandatory step prior to release. This is not optional. Please open a new PR containing the markdown files and assign it to me for review. Thank you. |
Thanks, the new PR is opened here for the doc: |
Summary
This PR adds the FSDP2 knob
distributed.multimodal.frozen_shardingfor fully frozen multimodal modules. It accepts:root(new default): keep frozen vision/audio towers and projectors in the always-run outer FSDP root. This keeps collective ordering aligned when modality execution differs across data-parallel ranks.per_layer: shard the frozen modules individually. This preserves the previous dense-VLM behavior, but requires every rank in the FSDP group to execute or skip those units identically on every microbatch; selecting it logs a warning.replicate: exclude the frozen parameters from FSDP so every rank keeps a full copy without tower collectives.Before this PR, dense VLMs implicitly used
per_layer, while common MoE VLMs implicitly usedroot. This PR makesrootthe default for both code paths. The measured Gemma4 MoE example explicitly selectsreplicate; five rank-uniform text-only Gemma4 examples explicitly retainper_layer, including two joint-drafter examples selected from paired measurements.Modules containing any trainable parameters keep their normal layer/container sharding. Nested dense and MoE VLM modules use the same policy resolution, including Gemma4's nested vision tower and projector.
For nested MoE/VLM models,
rootis rejected only whenwrap_outer_model=Falseleaves a fully frozen multimodal module outside the inner text-model FSDP root. Those models can enable the outer root or chooseper_layerwith rank-uniform execution orreplicate. The only current VLM-labeledwrap_outer_model=Falseexamples are LoRA benchmarks, whose adapters make their towers trainable at FSDP application time, so they are unaffected.The configuration guide and breaking-changes page document the knob, default change, tradeoffs, outer-root constraint, and
per_layerexecution contract.Config audit and measurements
The final audit found 85 tracked frozen-multimodal FSDP2 configs:
per_layer, leaving 47 that inheritroot; excluding four Qwen2.5 configs slated for deprecation leaves 43 current configs inheriting the changed default.per_layer(2 based on paired measurements), and 1 Gemma4 MoE config usesreplicatebased on paired measurements.Paired 30-step H100 measurements used warmup-excluded mean throughput as the preselected decision metric. Each policy cell reports
mean throughput delta; peak memory/GPU deltarelative toroot; a negative memory delta means lower peak memory:per_layervsroot(throughput; memory/GPU)replicatevsroot(throughput; memory/GPU)per_layer(before) →root(after)per_layer(before) →root(after)per_layer(before) →root(after)per_layer(before) →root(after)root(before) →replicate(after)per_layer(before) →per_layer(after)per_layer(before) →per_layer(after)per_layer(before) →per_layer(after)per_layer(before) →per_layer(after)per_layer(before) →per_layer(after)The full Gemma4 and Ministral3 train-loss sequences and validation losses matched exactly across all three policies. For Gemma4,
replicateis only 0.93% slower thanper_layerby measured mean throughput, so it is the safer example selection with essentially the same performance.The two joint-drafter pairs also had identical 30-step train-loss sequences and validation loss. The 4B result was repeated in reversed order and reproduced the throughput delta (+25.24%).
All five explicit
per_layerexamples provide only text batches to the VLM recipe, so every rank uniformly skips the frozen multimodal modules and satisfies the collective-ordering contract. The E4B CP16 recipe was originally validated when added, but current main has since moved from Transformers 5.8.1 to 5.12.1 and refactored CP dispatch. Its untouched path first fails the newer explicit shared-KV contract; a benchmark-only compatibility bridge gets past that error, after which both policies reproduce the same CP-ring stall before step 0. This is a separate current-main dense-CP regression and does not change the rank-uniform safety argument for retaining its previousper_layertopology.The earlier retained Gemma4 E4B matrix measured only +0.57% for replication. The deprecated Qwen2.5-VL result is supplemental only. Qwen3, Gemma3, and Ministral3 keep the
rootdefault because their gains were small or non-reproducible.All Gemma3, Gemma4, and Ministral3 policy matrices had identical train-loss sequences; the dedicated distributed regression provides root/per-layer optimizer-update parity and asymmetric-execution coverage.
Validation
14341819,1 passed.635 passed, 1 skipped.5 passed.14324681(4B) and14324720(31B), 30-step losses and validation loss identical.replicatererun: job14337370, 30/30 steps completed.14297661,14297677,14297753,14297767,14299169, and14323820.ruff format,ruff check, andgit diff --checkon the latest merged head.