Repository navigation
Commit e0eb281
Composite lm head tp plan (#49080)
* Declare the lm_head TP plan on every model that can tie it
`tie_word_embeddings` has the config shard `embed_tokens` `embedding_rowwise`,
and a tied head IS that parameter — so a head carrying no plan entry of its own
hands `F.linear` a plain input and a DTensor weight. 81 classes already declare
one; the composites that wrap them did not, because they keep their plan on
`text_config` rather than the outer config. 57 classes are affected.
Tying is a per-checkpoint flag, so the entry belongs on every class that CAN
tie, not only those whose shipped config does.
`test_tied_head_has_a_tp_plan_entry` pins it. The existing
`test_tp_plan_matches_params` checks the converse — that an entry names a real
module — so nothing caught an entry that was simply absent. It fails on 57
classes without this change.
Measured on 8xB200 with an untied head, so both arms are valid, against a
202048x4096 head (torch.compile, cudagraphs):
tp decode with/without weights per rank
2 0.674 / 0.732 ms (-8%) 2.844 / 3.615 GiB
4 0.689 / 0.737 ms (-7%) 2.193 / 3.350 GiB
8 0.724 / 0.802 ms (-10%) 1.867 / 3.216 GiB
Prefill is a wash (+2.8% at tp=2, -2.2% at tp=4 and 8). Eager numbers are not
reported: decode is host-bound there and the sign of the delta flips between TP
sizes.
Also drops `ColwiseParallel.validate_param`, which refused an output size
indivisible by the world size. `Shard._to_replicate_tensor` pads each shard
before the all-gather and trims after, and has since torch 2.5, the floor in
setup.py -- the neighbouring `test_colwise_uneven_local_shapes` already covered
the same thing for plain colwise. Verified at 2 and 8 ranks against an
unsharded reference, including GotOCR2's 151860 vocabulary: forward exact, and
weight and bias gradients bit-identical, with dgrad matching the even case to
the same 1 ulp of float64.
`_tp_plan` lands after `pack_image_features` in DeepseekOcr2: a class-level
assignment placed before a raise-only method makes the modular converter drop
that method from the generated file.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* Declare the head plan once per inheritance chain
39 of the declarations the previous commit added were redundant: the modular
converter flattens a parent's class attributes into the child's generated file,
so a model inheriting from one that already declares the entry gets it without
restating it. `Llava` alone covers Aria, AyaVision (and Cohere2Vision through
it), FastVlm, GotOCR2, InternVL, MiniMaxM3, Mistral3, Ovis2, PerceptionLM and
VipLlava; `PaliGemma` covers the Gemma3/3n/4 chain; `Qwen2VL` covers
Qwen2.5-VL, Glm4v and its descendants. 18 declarations remain, one per chain.
Every generated file is byte-identical apart from two spots, both intended:
the converter-placement comment in DeepseekOcr2 is gone with the declaration
it explained, and the `Ernie4_5_VL_Moe` BC alias drops a copy it inherits from
`Ernie4_5_VLMoe` at runtime.
`Qwen3OmniMoeTalker` keeps its own entry — it was there already, and its head
is `codec_head` rather than `lm_head`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* Use GotOcr2's indivisible vocab in the uneven colwise-gather test
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Give uneven TP shards their global shape and test VLM heads end to end
`DTensor.from_local` infers the global shape as `local * world` unless told otherwise, so an
output or input that does not divide by the world size (a 151860 vocab at TP=8, an odd MLP
width) was padded by the gather and never trimmed. The colwise output and rowwise input hooks
now pass the real shape, read off the weight DTensor.
The TP mixin no longer rounds the tiny vocab up to the world size, which hid exactly this; its
backward comparison slices uneven shards at the true offset; and it reads the vocab and plans
off the text config, so GotOcr2 and GLM-4V-MoE now run the real multi-rank tests.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Regenerate MiniCPM-V 4.7 with the head plan it inherits from 4.6
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Review: take a sharded dim's full width from the module, and simplify the tied-head plan test
- An uneven last-dim shard's global width comes from the module's declared size (`out_features`,
`in_features`, `embedding_dim`) rather than its weight's shape, which a packed or quantized weight does not
carry (packed FP4 halves `in_features`).
- The tied-head test reads the head and embedding through `get_output_embeddings` / `get_input_embeddings`, over
the generative classes.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Review: make the last-dim shard helper a `TensorParallelLayer` static method with a shorter docstring
It is shared by `ColwiseParallel`'s output and `RowwiseParallel`'s input, so it lives on their common base.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Review: keep this PR to the tied-head plans, move uneven sharding to its own PR
The failure this PR fixes is a tied `lm_head` without a TP-plan entry on composite models: it reads the
`embed_tokens` weight a tying config shards, so `F.linear` got a plain input and a DTensor weight. The support for
dims that do not divide by the TP size (the explicit global shape on `from_local`, dropping the colwise-gather
divisibility check, uneven backward slicing, the un-rounded test vocab and GotOcr2's TP tests) moves to its own PR.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* TP: split a linear layer unevenly when its width does not divide by the TP size
A colwise layer whose output is gathered (an `lm_head`) had to divide by the TP size, so a model with a vocab such
as GotOcr2's could not use TP. A linear layer can now split unevenly: the last rank holds a shorter slice, and the
colwise output and rowwise input wrap their local slice with the module's declared width (`out_features`,
`in_features`; a packed or quantized weight's shape does not show it), since `DTensor.from_local` would otherwise
assume every rank holds the same width. A module without that width, such as an embedding, still has to divide.
The TP mixin keeps the tester's vocab as is and slices uneven gradient shards at their true offset; GotOcr2 joins
the multi-rank tests.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Keep this PR to the tied-head plans; uneven linear sharding moves to the linear/embedding TP split PR
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Review: drop the `is_torch_available` guard around GLM-4V MoE's `causal_lm_class`
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Anton Vlasjuk <73884904+vasqu@users.noreply.github.com>1 parent 9284c01 commit e0eb281
83 files changed
Lines changed: 121 additions & 14 deletions
File tree
- src/transformers/models
- aria
- aya_vision
- cohere2_vision
- cohere_compass
- cosmos3_edge
- cosmos3_omni
- deepseek_ocr2
- deepseek_vl_hybrid
- deepseek_vl
- diffusion_gemma
- ernie4_5_vl_moe
- exaone4_5
- fast_vlm
- florence2
- fun_asr_nano
- gemma3n
- gemma3
- gemma4_unified
- gemma4
- glm46v
- glm4v_moe
- glm4v
- glm5_next
- glm_image
- glm_ocr
- glmasr
- got_ocr2
- granite4_vision
- granite_speech_plus
- granite_speech
- hyperclovax_vision_v2
- idefics2
- idefics3
- internvl
- janus
- kimi_k25
- lfm2_vl
- lighton_ocr
- llama4
- llava_next_video
- llava_next
- llava_onevision
- llava
- minicpmv4_6
- minicpmv4_7
- minimax_m3_vl
- mistral3
- muse_glimmer
- neomme
- ovis2
- paddleocr_vl
- paligemma
- perception_lm
- pp_formulanet
- qianfan_ocr
- qwen2_5_omni
- qwen2_5_vl
- qwen2_vl
- qwen3_5_moe
- qwen3_5
- qwen3_asr
- qwen3_omni_moe
- qwen3_vl_moe
- qwen3_vl
- qwen4_exp
- smolvlm
- step3p7
- video_llama_3
- video_llava
- vipllava
- voxtral_realtime
- tests
- models/glm4v_moe
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
978 | 978 | | |
979 | 979 | | |
980 | 980 | | |
| 981 | + | |
981 | 982 | | |
982 | 983 | | |
983 | 984 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
297 | 297 | | |
298 | 298 | | |
299 | 299 | | |
| 300 | + | |
300 | 301 | | |
301 | 302 | | |
302 | 303 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
252 | 252 | | |
253 | 253 | | |
254 | 254 | | |
| 255 | + | |
255 | 256 | | |
256 | 257 | | |
257 | 258 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1383 | 1383 | | |
1384 | 1384 | | |
1385 | 1385 | | |
| 1386 | + | |
1386 | 1387 | | |
1387 | 1388 | | |
1388 | 1389 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1160 | 1160 | | |
1161 | 1161 | | |
1162 | 1162 | | |
| 1163 | + | |
1163 | 1164 | | |
1164 | 1165 | | |
1165 | 1166 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
517 | 517 | | |
518 | 518 | | |
519 | 519 | | |
| 520 | + | |
520 | 521 | | |
521 | 522 | | |
522 | 523 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1553 | 1553 | | |
1554 | 1554 | | |
1555 | 1555 | | |
| 1556 | + | |
1556 | 1557 | | |
1557 | 1558 | | |
1558 | 1559 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
233 | 233 | | |
234 | 234 | | |
235 | 235 | | |
| 236 | + | |
236 | 237 | | |
237 | 238 | | |
238 | 239 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
414 | 414 | | |
415 | 415 | | |
416 | 416 | | |
| 417 | + | |
417 | 418 | | |
418 | 419 | | |
419 | 420 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1586 | 1586 | | |
1587 | 1587 | | |
1588 | 1588 | | |
| 1589 | + | |
1589 | 1590 | | |
1590 | 1591 | | |
1591 | 1592 | | |
| |||
0 commit comments