Repository navigation
AutoTP: shard an untied input embedding along the vocabulary (`vocab_… - #8859
pengdurice wants to merge 1 commit into
Conversation
…parallel_embedding`) Signed-off-by: pengdurice <pengduhit@gmail.com>
|
Thanks for picking this up. This fills the untied half of the tied/untied unification in RFC #8173 (#8582 handled tied + vocab-parallel head), so it fits well. A few points from tracing the paths on master:
|
Part of: #8672 (Q4 2026 roadmap), "Enable training of large scale models".
Summary
vocab_parallel_lm_head(#8309) shards an input embedding only when it is tied to the output layer. An untied inputembedding stays replicated on every tensor-parallel rank: on Qwen2.5-72B at TP 8 it is 1.25B of each GPU's 10.18B
parameters (12%), with its gradient, master copy and Adam states, and its gradient is the last one produced in
backward. This PR adds
tensor_parallel.vocab_parallel_embedding(defaultfalse): AutoTP replaces the model'suntied
nn.Embeddingby the existingVocabParallelEmbedding(1/tp of the rows per rank, masked lookup, sum overthe TP group).
Results
Qwen2.5-72B, 4 nodes x 8 H200 (EFA), AutoTP 8 x ZeRO-1 over 4, micro-batch 2, 64 x 8,192 tokens per step, bf16 with
fp32 master weights and Adam states, no recompute, Liger kernels for RMSNorm, rotary embedding and SwiGLU (applied by
our benchmark script); the two runs in one allocation, with this code in our study tree (together with the AutoTP
sequence-sharding changes, which are separate PRs):
wall_clock_breakdown)Duplicate check
Searched issues and pull requests on 2026-10-18 for
vocab_parallel_embedding, "untied embedding AutoTP" andVocabParallelEmbedding untied: #8309 and #8680 handle tied embeddings, #8173 (open RFC) discusses sharding outputlayers; none shards an untied input embedding.
The change
deepspeed/module_inject/layers.py(+26)shard_untied_input_embedding(model, mp_group, tp_meta): replacesmodel.get_input_embeddings()by aVocabParallelEmbedding; returnsNonewhen it already is one (a tied embedding sharded byvocab_parallel_lm_head); raisesNotImplementedErrorwhen the embedding's weight is shared with another module, so a tied embedding is never untieddeepspeed/runtime/engine.py(+6)finalize_autotp, before the replicated-gradient hooks are registered, when the option is setdeepspeed/runtime/tensor_parallel/config.py(+7)docs/_pages/config-json.md,docs/_tutorials/autotp-training.mdtests/unit/v1/autotp/test_autotp_training.py(+83)TestVocabParallelEmbeddingTests
TestVocabParallelEmbedding(2 ranks, AutoTP 2, a 2-layer untied Llama built from a config):test_matches_single_device_training(ZeRO 0 and 1): the input embedding becomes aVocabParallelEmbeddingwithhalf of the rows; with tokens from both halves of the vocabulary, the losses of 2 SGD steps match the unsharded
model, and the gathered embedding weight matches the unsharded model's after them.
test_rejects_tied_embedding_without_vocab_parallel_lm_head: a tied embedding withvocab_parallel_lm_head: falseraises instead of being untied from the output layer.
Hardware: 1 node, 4 x H200 (driver 580.126.09), torch 2.8.0+cu126, transformers 5.15.1, pytest 9.1.1, pytest-forked
1.7.5.
pre-commit run --filespasses on every changed file.Compatibility
tp_metatoVocabParallelEmbeddingvocab_parallel_lm_head; with it disabled, an errorget_input_embeddings()is not annn.EmbeddingValueErrorVocabParallelEmbeddingAI assistance
This change, its tests and this description were prepared with AI assistance (Claude).
🤖 Generated with Claude Code