Sparse MoE FFN
DeepSeek-V3
Hard
Full sparse MoE feedforward block
Independent study note. Written from the public paper and official code. This is not TensorTonic Plus and does not reproduce their exercises, starter code, or tests. For the official version, subscribe on TensorTonic.
Overview
After the first three dense layers, every DeepSeek-V3 feed-forward is a DeepSeekMoE block: one always-on shared SwiGLU plus 256 routed SwiGLUs of which 8 fire per token. That is the compute that makes 671B total parameters collapse to about 37B activated (including attention and embeddings). This note is the assembly of pieces covered elsewhere — sigmoid top-k routing, auxiliary-loss-free bias, shared expert — into one residual FFN. The paper's design goals here are fine-grained experts (many small FFNs instead of few wide ones), isolation of shared knowledge, balanced load without token dropping, and node-limited communication so DualPipe can hide all-to-all.
How it works
Residual form (paper eq. 12). With \mathbf{u}_t the pre-normed FFN input:
\mathbf{h}_t'=\mathbf{u}_t+\sum_{i=1}^{N_s}\operatorname{FFN}_i^{(s)}(\mathbf{u}_t)+\sum_{i=1}^{N_r}g_{i,t}\,\operatorname{FFN}_i^{(r)}(\mathbf{u}_t).
On 671B: N_s=1, N_r=256, K_r=8, each expert inner width 2048, hidden d=7168. Official Block adds the \mathbf{u}_t skip outside MoE; the module returns shared + routed only.
Each expert is SwiGLU, same algebra as the dense prefix MLP:
\operatorname{FFN}(\mathbf{u})=\mathrm{W}_2\bigl(\operatorname{SiLU}(\mathrm{W}_1\mathbf{u})\odot\mathrm{W}_3\mathbf{u}\bigr),\quad \mathrm{W}_1,\mathrm{W}_3\in\mathbb{R}^{2048\times 7168},\;\mathrm{W}_2\in\mathbb{R}^{7168\times 2048}.
Routed copies are local Linears (expert-parallel shards). The shared path is one MLP of inner width N_s\cdot 2048.
Routing. Affinities s_{i,t}=\operatorname{Sigmoid}(\mathbf{u}_t^{\top}\mathbf{e}_i). Top-K_r is taken on s_{i,t}+b_i (and after group masking: 8 groups, keep 4, group score = sum of top-2 when bias is present). Gates $$ are the unbiased selected s_{i,t} renormalized over the K_r winners, then multiplied by route_scale=2.5. Tokens that miss a local expert contribute 0 to that shard; shards all_reduce the routed sum.
Packed forward (official). Flatten (B,S,d)\to(T,d). Gate returns weights (T,K_r) and indices (T,K_r). For each local expert i, gather the tokens where indices==i, run the SwiGLU, scale by the matching weights, and scatter-add into a zero buffer $$. Compute z=\operatorname{FFN}^{(s)}(\mathbf{u}) on all T tokens. Return (y+z) reshaped. No token is dropped: empty experts are skipped, but every token still receives shared + its K_r routed outputs.
What is specified vs. inferred. Equations (12)–(16), N_s,N_r,K_r,M=4, and “no token-dropping” are in the report. Expert-parallel index ranges, fused shared width, and route_scale come from inference/model.py and config_671B.json. The \gamma bias update and \mathcal{L}_{\mathrm{Bal}} are training-only and absent from the inference file.
Activated FFN FLOPs per token are one shared SwiGLU plus eight routed SwiGLUs, not 257. Attention is MLA and is outside this block.
Official code
inference/model.py: Block.ffn is MLP when layer_id < n_dense_layers (3) else MoE. MoE owns Gate, an ModuleList of Expert (or None for non-local ids), and shared_experts. Expert.forward is the SwiGLU above. 671B numbers: inference/configs/config_671B.json. Distributed ranks set experts_start_idx = rank * (N_r / world_size).
Watch-outs
- Applying the residual twice (inside
MoEand inBlock) doubles the skip. OfficialMoEdoes not add x. - Softmax routing without winner-only renormalization, or gating the shared expert, is a different FFN than V3.
- Computing all 256 experts and masking is correct but not what the official loop does; it iterates only local experts with nonzero
bincount. - Inner width 2048 is per expert. A single dense FFN of width 8\times 2048 is not equivalent: it lacks sparsity and the shared/routed split.
- Group-limited routing is part of this block during training/inference of 671B. A bare top-8 over 256 experts ignores the M=4 node cap.
Sources
- Paper: DeepSeek-V3 Technical Report, arXiv:2412.19437 (§2.1 DeepSeekMoE, eqs. 12–16; no token-dropping; §4 widths)
- Code: deepseek-ai/DeepSeek-V3 (
inference/model.py, classesMoE,Gate,Expert,MLP,Block)