Do not mark replicated weights as tensor-model-parallel - #715
Open
wenchenvincent wants to merge 3 commits into
Open
Do not mark replicated weights as tensor-model-parallel#715wenchenvincent wants to merge 3 commits into
wenchenvincent wants to merge 3 commits into
Conversation
Linear.reset_parameters marked every weight is_parallel=True regardless of parallel_mode. For parallel_mode=None the weight is replicated on every TP rank, so downstream consumers that use the attribute to de-duplicate -- notably Megatron's param_is_not_tensor_parallel_duplicate(), which gates get_grads_for_norm() -- admit it to the global gradient norm once per rank instead of once. The norm is assembled as a sum of squares across ranks, so the contribution is added tp_size times. Inflation follows sqrt(1 + (TP-1)*f), where f is the replicated weights share of the true squared norm. Measured at TP=8 on MI355X: DeepSeek-V4-Flash 3.763 -> 2.472 (1.52x, f~0.19) DeepSeek-V3 12.228 -> 9.011 (1.36x, f~0.12) This is primarily a diagnostic bug: the reported norm is what practitioners use to judge training health, tune --clip-grad and compare against reference curves. The effect on weights is optimizer-dependent -- clipping is a global uniform rescale, which Adam largely absorbs and Muon absorbs exactly, while SGD sees it in full. Affects architectures that deliberately replicate weights carrying real gradient energy. Megatron MLA passes parallel_mode=duplicated for q_down_proj/kv_down_proj, so DeepSeek-V2/V3/V3.2-family models take this path. Restores TE own default: _MODEL_PARALLEL_ATTRIBUTE_DEFAULTS declares tensor_model_parallel=False for a non-parallel tensor. Introduced upstream in 0449033 (2023-02-10).
Mechanism, the sqrt(1 + (TP-1)*f) scaling law, which axis is affected, optimizer-dependent impact (SGD full / Adam second-order / Muon none), affected architectures, history bisect, fix and caveats. Evidence from two MLA models at TP=8 on MI355X: DeepSeek-V4-Flash (1.52x) and DeepSeek-V3 (1.36x). The DeepSeek-V3 run uses Megatron pretrain_gpt.py with --multi-latent-attention --transformer-impl transformer_engine and no third-party model code.
Both accept parallel_mode: Optional[str] = None and mark weights is_parallel=True unconditionally, exactly as Linear did (1 site in LayerNormLinear, 2 in GroupedLinear). LayerNormMLP is NOT affected: it has no parallel_mode parameter and is structurally column-then-row, so is_parallel=True is always correct there. The bias handling below each weight loop is already correct -- it branches on parallel_mode (row sets sequence_parallel, column marks the bias, None marks nothing). Only the weight marking ignored the mode. These two are latent rather than triggered: no Megatron wrapper instantiates them with parallel_mode=None today (TELayerNormColumnParallelLinear passes column; TEColumnParallelGroupedLinear/TERowParallelGroupedLinear pass column/row). They are reachable through TE public API, and fixing them keeps the three call sites consistent. Only the Linear fix is backed by measurement.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Linear.reset_parametersmarks every weightis_parallel=Trueregardless ofparallel_mode. Forparallel_mode=Nonethe weight is replicated on every TP rank, soMegatron's
param_is_not_tensor_parallel_duplicate()— which gatesget_grads_for_norm()— admits it once per rank instead of once. The norm is assembled as a sum of squares
across ranks, so the contribution is added
tp_sizetimes and the reported gradient normis inflated.
Measured (MI355X, gfx950, TP=8, EP=8, bf16, fixed seed)
The ratio is constant per-iteration — the signature of a counting error, not a numerical
one. Loss is unchanged in both (differences in the 4th–5th decimal, no systematic drift),
confirming only the clipping scale moves, not the mathematics.
The DeepSeek-V3 run is Megatron's own
pretrain_gpt.pywith--multi-latent-attention --transformer-impl transformer_engineand no third-partymodel code — reproducible with upstream components alone.
Why this is architecture-specific
Inflation follows
sqrt(1 + (TP-1)*f)wherefis the replicated weights' share of thetrue squared norm — gradient energy, not parameter count. Inverting the measurements
gives f ≈ 18.8% (V4-Flash) and 12.2% (V3), against a ~0.3% parameter share.
For a standard transformer every linear is column- or row-parallel, so
is_parallel=Trueis correct and the bug cannot trigger. It needs an architecture that deliberately
replicates weights carrying real gradient energy. MLA is exactly that — the KV latent is
shared by every head, and the down-projection feeds a column-parallel up-projection that
needs the complete input on every rank. Megatron's MLA passes
parallel_mode='duplicated'for
q_down_proj/kv_down_proj, so DeepSeek-V2/V3/V3.2-family models take this path.It also scales with TP: at f≈0.19 the law predicts 1.53x at TP=8 and 1.96x at TP=16.
Impact
Primarily diagnostic. The gradient norm is what practitioners use to judge training
health, tune
--clip-grad, detect instability and compare against reference curves — andit is wrong by 36–52% on these models.
Weight-level impact is optimizer-dependent, because Megatron's clipping is a global,
norm-based rescale that preserves direction and relative weighting:
m -> c·m,v -> c²·v, soccancels except throughεMegatron defaults to Adam, so most users see a wrong number rather than degraded
training. An SGD configuration sees the full effect.
Fix
Restores TE's own default —
_MODEL_PARALLEL_ATTRIBUTE_DEFAULTSdeclarestensor_model_parallel: Falsefor a non-parallel tensor. TE never reads the attributeback; it is set purely for downstream consumers.
LayerNormLinear,GroupedLinearandLayerNormMLPshould be checked for the samepattern — this PR changes only
Linear.History
Introduced upstream in NVIDIA/TransformerEngine
044903374(2023-02-10, "QKV parametersunfused path fixes and optimization" #66). Bisect: the preceding commit
78b4e9339has noweight-marking call. The initial code drop marked only biases, which in column-parallel
layers genuinely are sharded;
parallel_mode: Optional[str] = Nonewas already reachablewhen the unconditional marking landed. Everything since is refactoring. Present in both
NVIDIA
mainand ROCmdev.Caveats
balance differs from production;
fand the ratio would shift at full depth.propagate via
copy_tensor_model_parallel_attributes), not measured.end; no convergence comparison against a reference curve has been run.