Skip to content

[AutoTP] Add optional Liger vocabulary-parallel cross entropy - #8540

Open
0z5a wants to merge 12 commits into
deepspeedai:masterfrom
0z5a:feat/autotp-liger-vocab-ce
Open

0z5a wants to merge 12 commits into
deepspeedai:masterfrom
0z5a:feat/autotp-liger-vocab-ce

Conversation

@0z5a

@0z5a 0z5a commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Dependency and review scope

Depends on #8309 (PR-B from #8173), currently open. This branch is based on its head 1b4ba6b162e87b10bedbb7316466bd877e2cb278; inherited PR-B commits retain their original authorship. The final commit is the optional Liger backend work. Please review that commit for this PR's independent changes. This is a draft until PR-B lands; the master comparison currently includes the dependency changes.

This addresses the optional fused CE and memory-profiling direction in #8173. It does not include row-parallel output-head training (#8538) or coupled tied-embedding sharding.

Changes

  • Add opt-in tensor_parallel.vocab_parallel_ce_backend: "liger" alongside vocab_parallel_lm_head: true; default "torch" remains dependency-free.
  • Lazy-load Liger's public vocabulary-parallel CE function (liger-kernel>=0.8.1) and retain the existing reduction / causal-label-shifting contract.
  • Use identical gathered shard metadata to select Liger on every TP rank only for equal vocabulary shards, nonempty CUDA tokens, and FP32/FP16/BF16 logits. Uneven shards or unsupported layouts uniformly fall back to the PyTorch reference.
  • Reject repeated retained-graph backward and higher-order gradients for Liger's destructive saved-buffer backward instead of silently producing incorrect gradients.
  • Add optional-backend numerical and real AutoTP training integration coverage, and document the compatibility boundaries.

This fuses CE only, not the linear projection. Local vocabulary logits are still materialized.

Real-device validation

jk01: two NVIDIA L20 GPUs (46068 MiB each), isolated container, Python 3.12.3, PyTorch 2.13.0+cu130, CUDA 13.0, Transformers 5.14.1, Triton 3.7.1, liger-kernel 0.8.2.

  • Partition/config and non-distributed CE regressions: 42 passed, 7 distributed cases deselected in that regression invocation.
  • Two-rank numerical tests: FP32/FP16/BF16, none/sum/mean, even/uneven vocab, ignored targets, unchanged input logits, retained-graph rejection, and higher-order rejection passed.
  • Real DeepSpeed-engine training: vocab 34 (Liger) and vocab 35 (uneven fallback), each five optimizer updates, with two accumulated micro-batches per update. SGD LR 0.05, FP32, ZeRO 0, clipping explicitly disabled. Logits, loss, gradients, updated sharded head weights/biases, and replicated projection weights/biases agree with an independent unsharded PyTorch model.
  • Changed-file pre-commit checks and git diff --check passed.

The distributed integration methods in TestLigerVocabParallelCE were executed via two-rank torchrun on the actual devices. Reproduce with pytest:

PYTHONPATH=.:tests python3 -m pytest tests/unit/v1/sequence_parallelism/test_liger_vocab_parallel_cross_entropy.py -v -s

Memory profile

Compared local linear + vocabulary-parallel CE forward/backward + five SGD updates, two micro-batches each, after kernel warm-up and resetting weights/allocated peaks. BF16, TP=2, 1024 tokens per rank, hidden=128, global vocabulary=65536, local vocabulary=32768. Statistics are the maximum across ranks.

Backend Peak allocated Incremental peak over baseline Short-run elapsed
PyTorch 512247296 bytes (488.52 MiB) 478160384 bytes 0.0606 s
Liger 310922240 bytes (296.52 MiB) 276834304 bytes 0.0779 s

Peak allocated decreases approximately 39.3%; incremental peak decreases approximately 42.1%. Losses and final local weights agree. This is a short single-sample memory comparison, not evidence of throughput speedup; allocated memory is not total device or reserved memory.

Four-GPU TP x SP integration, mixed-precision/ZeRO checkpoint round trips, and large-model convergence are not validated by this two-GPU run.

jinyouzhi and others added 12 commits September 8, 2026 10:19
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Jin, Youzhi <youzhi.jin@intel.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Jin, Youzhi <youzhi.jin@intel.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Jin, Youzhi <youzhi.jin@intel.com>
Require an explicit sequence-parallel group when the legacy wrapper gathers losses, and document the distinct backward conventions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Jin, Youzhi <youzhi.jin@intel.com>
Replace the output head in heuristic AutoTP and preserve original tied-weight evidence before embedding traversal mutates parameters.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Jin, Youzhi <youzhi.jin@intel.com>
Resolve and validate the heuristic output head before transformer partitioning, cache the candidate for replacement, and skip tied-weight scans when the feature is disabled.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Jin, Youzhi <youzhi.jin@intel.com>
New files carry only the SPDX identifier and team line.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Jin, Youzhi <youzhi.jin@intel.com>
Fail when vocab_parallel_lm_head finds no supported head instead of degrading
into an ordinary gathered head with no distributed loss, and warn when the flag
supersedes an explicit lm_head spec from partition_config or a HuggingFace
tp_plan.

Also partition the embedding with a row spec in the tied-head regression so it
exercises the captured tie identities; the previous embedding_rowwise plan
converts to a skip spec, which left the embedding untouched and the guard
unreached.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Jin, Youzhi <youzhi.jin@intel.com>
Save and reload a vocab-parallel LM head and compare the causal-LM loss, since
no existing test exercises checkpoint paths for the VocabParallelLinear layout.
The reloaded model starts from a different initialization so an unrestored
checkpoint cannot pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Jin, Youzhi <youzhi.jin@intel.com>
Signed-off-by: 0z5a <dezhen.lu@student.uni-tuebingen.de>
@0z5a 0z5a closed this Sep 16, 2026
@0z5a 0z5a reopened this Sep 16, 2026
@0z5a
0z5a marked this pull request as ready for review September 16, 2026 11:48

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5453799d02

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

and target.numel() > 0
and _uniform_vocab_shards[(tp_group, local_vocab_size, vocab_start_index, vocab_end_index)])
if use_liger:
loss = _liger_vocab_cross_entropy(vocab_parallel_logits, target.to(dtype=torch.long), tp_group, ignore_index)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Avoid treating the default world as the TP group

When a multi-rank data-parallel job calls the public API with backend="liger" and leaves tp_group=None, the preceding metadata logic treats TP as disabled, but this call passes None to Liger's distributed group argument, where it denotes the default world process group. Liger then interprets the DP replicas' full-vocabulary logits as separate vocabulary shards, producing an incorrect global loss and gradients. Fall back to the PyTorch implementation in this case or pass an explicit singleton TP group.

Useful? React with 👍 / 👎.

Comment on lines +56 to +57
vocab_parallel_ce_backend: Literal["torch", "liger"] = "torch"
"""Optional Liger CE acceleration; the PyTorch reference remains the default."""

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Add the mandatory commit sign-off

Commit 5e07eda8cb904aad0dce2b9a9df136255b432c78 is a non-merge commit but its message has no Signed-off-by trailer, so it does not satisfy this repository's commit/CI requirements and will fail DCO-style validation. Recreate the commit with the configured author identity and the required sign-off.

AGENTS.md reference: AGENTS.md:L8-L8

Useful? React with 👍 / 👎.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants