Skip to content

[PyTorch] DeepSeekV3Layer: full MoE transformer layer (MLA + DeepSeek MoE) - #36

Draft
pggPL wants to merge 7 commits into
mainfrom
deepseek_v3_layer
Draft

[PyTorch] DeepSeekV3Layer: full MoE transformer layer (MLA + DeepSeek MoE)#36
pggPL wants to merge 7 commits into
mainfrom
deepseek_v3_layer

Conversation

@pggPL

@pggPL pggPL commented Aug 18, 2026

Copy link
Copy Markdown
Owner

Description

Adds transformer_engine.pytorch.models — a namespace for model-specific layers composed from TE modules — with a DeepSeekV3 transformer layer analogous to TransformerLayer, exercising TE's MoE and MLA features end to end.

MultiLatentAttention (models/deepseek_v3/multi_latent_attention.py): low-rank q/kv latents with RMSNorm fused into the up-projections (LayerNormLinear(normalization="RMSNorm")), decoupled RoPE/NoPE head split with a single shared key rope head (fused RoPE via apply_rotary_pos_emb(fused=True)), core attention through DotProductAttention with asymmetric head dims kv_channels=(qk_nope+qk_rope, v) so the cuDNN fused attention backend is used where supported (SM100+ for 192/128 training). TP via column/row parallel projections.

DeepSeekV3MoE (models/deepseek_v3/moe.py): fused sigmoid router with aux-loss-free expert bias and node-limited grouped top-k (fused_topk_with_score_function) plus an update_expert_bias() helper; routed experts as te.ops.Sequential(GroupedLinear, ScaledSwiGLU(32), GroupedLinear) which auto-fuses into the CuTe grouped-GEMM MLP on supported hardware and runs the identical unfused path elsewhere; routing probs applied per-token inside the activation, so merge is plain accumulation. Token routing either local (moe_permute_with_probs/moe_unpermute) or expert-parallel over NCCL (ep_dispatch/ep_combine with EpBuffer). Optional shared expert (te.ops SwiGLU MLP).

DeepSeekV3Layer (models/deepseek_v3/transformer_layer.py): pre-RMSNorm + MLA, then dense LayerNormMLP (RMSNorm+swiglu, first dense layers) or DeepSeekV3MoE, with residual connections.

Type of change

  • Documentation change (change only to the documentation, either a fix or a new content)
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Infra/Build change
  • Code refactoring

Changes

  • New transformer_engine/pytorch/models/ namespace with models/deepseek_v3/ subpackage (MultiLatentAttention, DeepSeekV3MoE, DeepSeekV3Layer), exported via transformer_engine.pytorch.models
  • Docs: Model-specific layers section in docs/api/pytorch.rst
  • Tests: tests/pytorch/test_deepseek.py (MLA fwd/bwd, MoE variants incl. grouped routing + shared expert, numeric check against a dense reference, dense/MoE layer fwd/bwd) — 8 passed on RTX Ada; distributed suite skips cleanly there (SM89, 1 GPU)
  • Distributed EP test: tests/pytorch/distributed/test_deepseek_ep.py + run_deepseek_ep.py (EP vs all-local numeric equivalence incl. all-reduced expert wgrads, full-layer EP smoke; verified on 4x GB300 (lyris, arm64, SM103): all ranks pass)
  • TODO (follow-ups): CUDA-graph/torch.compile coverage, YaRN rope scaling, optional seq-wise aux loss

Checklist:

  • I have read and followed the contributing guidelines
  • The functionality is complete
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

🤖 Generated with Claude Code

pggPL and others added 7 commits August 18, 2026 12:37
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Pawel Gadzinski <pgadzinski@nvidia.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Pawel Gadzinski <pgadzinski@nvidia.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Pawel Gadzinski <pgadzinski@nvidia.com>
MultiLatentAttention: low-rank q/kv latents (RMSNorm fused into
LayerNormLinear up-projections), decoupled RoPE/NoPE head split with a
shared key rope head, DotProductAttention with kv_channels=(qk, v) for
the cuDNN fused backend.

DeepSeekV3MoE: fused sigmoid router with aux-loss-free expert bias and
grouped top-k, routed experts as te.ops GroupedLinear+ScaledSwiGLU+
GroupedLinear (CuTe fused grouped MLP on supported HW), probs applied
per-token in the activation, local permute/unpermute or NCCL expert
parallelism via ep_dispatch/ep_combine, optional shared expert.

DeepSeekV3Layer: pre-RMSNorm + MLA and dense LayerNormMLP (RMSNorm,
swiglu) or MoE with residual connections.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Pawel Gadzinski <pgadzinski@nvidia.com>
run_deepseek_ep.py checks the EP path against the all-experts-local
path numerically (forward, input/gate grads, all-reduced expert wgrads)
and smoke-tests the full layer with EP. Also size the default EP recv
capacity for per-expert alignment padding and the fused grouped MLP's
row-count requirement.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Pawel Gadzinski <pgadzinski@nvidia.com>
The per-expert wgrad check called all_reduce on different tensors per
rank (rank-local experts), corrupting the reference grads; reduce every
expert's grad on every rank instead. Also pass zero-filled recv/grad
buffers to ep_dispatch/ep_combine so alignment-padding rows inside the
grouped-GEMM m_splits can never poison expert wgrads.

Verified on lyris (4x GB300, arm64): run_test_deepseek_ep.sh passes on
all ranks (EP forward/dgrad/gate-grad/expert-wgrad match the all-local
reference; full-layer EP smoke passes).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Pawel Gadzinski <pgadzinski@nvidia.com>
Move the Triton MLA RoPE kernels (Megatron-LM
fused_mla_yarn_rope_apply port) from tests/pytorch/attention/
mla_rope_utils.py into models/deepseek_v3/mla_rope.py and use them in
MultiLatentAttention: the q kernel rotates the rope slice in place and
the kv kernel assembles key/value in a single pass, removing the
torch.cat/expand/contiguous copies (~10% of layer GPU time). PyTorch
fallback (same convention) covers missing Triton and bshd.

Fix a latent bug from the test util: the q backward kernel assumed a
contiguous incoming gradient, but cuDNN attention backward can hand
over a strided one (allocator-state dependent IMA). The old test file
stays as a compat shim. Add a Triton-vs-PyTorch parity test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Pawel Gadzinski <pgadzinski@nvidia.com>
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.

1 participant