Illustration

Reading Open-Weight Recipes, Part 1:

What 2025–26 Model Reports Disclose About Pretraining

Written by Martin Ziqiao Ma

Notes on the pretraining design choices disclosed in the 2025–26 open-weight model reports: scale, mixture of experts, attention, position, the residual stream, multi-token prediction, multimodal input, optimizers, schedules, stability, numerics and data. Each chapter explains the mechanism, works a real example, and gives the reasons the labs themselves stated.

Disclaimer: This blog is compiled and edited with help from LLMs. Every number links to the public document it came from, so please check the source before citing it.

This is Part 1 of Reading Open-Weight Recipes, a series where I review what open-weight model releases have written down about their training recipes between December 2024 and October 2026. The atlas indexes the disclosures lab by lab; these notes go through pretraining one design choice at a time, with the mechanism, a worked example using numbers from a released model, and the reasons the labs themselves gave.

The same caveats as the rest of the series apply. Everything here comes from the public reports of open-weight releases (plus Microsoft AI's reports, whose models are mostly closed-weight), so it describes what those labs chose to disclose. It is not a description of how frontier closed models are trained, and where a report is silent I don't fill the gap. These are personal notes, not written for, reviewed by, or endorsed by any lab covered here.

Before you start

Why do the 2025–26 open models look so different from the transformer in a textbook, and what decided each difference?

A textbook transformer has one kind of attention, one kind of feed-forward block, a fixed position encoding and an Adam optimizer. Between DeepSeek-V3 in December 2024 and MAI-Base-2 in October 2026, the labs in this review changed almost every one of those parts. Most of the changes have the same root cause: models became cheap enough to train at enormous scale, and expensive enough to serve that serving cost began to shape the architecture. Long agent sessions with hundreds of thousands of tokens of context made that pressure much stronger.

These notes take each design choice in turn. Each chapter has the same parts:

  • The question the chapter answers.
  • The mechanism, built up from the simple baseline to the 2025–26 designs, with a diagram, the equations and short pseudocode.
  • A worked example with real numbers from a released model.
  • Who uses it and why, quoting the labs' own reasons.
  • Trade-offs, three takeaways, and two check yourself questions with answers you can open.

The notes assume you know how a standard transformer works (embeddings, attention, feed-forward blocks, softmax and backpropagation) and are comfortable with matrix shapes. No prior knowledge of the newer designs is needed. Underlined numbers link to their source; hover them to see the exact quote or configuration value.

Notation

SymbolMeaningSymbolMeaning
Lnumber of layersN, Natotal and active parameters
dmodel width (hidden size)Dtraining tokens
h, hkvquery heads, key/value headsE, krouted experts, experts active per token
dhdimension of one attention headwsliding-window size
ncontext length in tokensdc, drMLA latent dimension, decoupled RoPE dimension
bbytes per stored numbermtokens selected by sparse attention
ηlearning rateSlinear-attention state matrix

Other symbols are local to the chapter that defines them. Layer ratios are written local : global for sliding-window models (5:1 means five sliding-window layers per global layer) and linear : full for linear-attention hybrids.

The models in these notes

The notes draw examples from fifteen labs: six that publish open-weight models and detailed reports (DeepSeek, Moonshot's Kimi, Z.ai's GLM, Xiaomi's MiMo, Google's Gemma and Thinking Machines' Inkling), one that publishes detailed reports on mostly closed-weight models (Microsoft AI's MAI), six open-weight labs the atlas added later (Alibaba's Qwen, MiniMax, StepFun, Ant's Ling, NVIDIA's Nemotron and Mistral), and the open-weight models of two more (OpenAI's gpt-oss and Meta's Llama 4 and Muse). "Total / active" gives all parameters and the parameters one token uses; "builds on" says whether the release is a new pretraining run or reuses an earlier one.

LabModelReleasedTotal / activeBuilds on
DeepSeekDeepSeek-V3Dec 2024671B / 37Bnew run
DeepSeek-V3.2-Exp, V3.2Sep, Dec 2025671B / 37BV3 lineage, sparse attention added by continued training
DeepSeek-V4 (Pro, Flash)Apr 20261.6T / 49B; 284B / 13Bnew run
DeepSeek-V4.1-FlashSep 2026552B + 196B memory / 16Bnew run
Kimi (Moonshot)MoonlightFeb 202516B / 3Bnew run (research)
Kimi K2Jul 20251.04T / 32.6Bnew run
Kimi LinearOct 202548B / 3Bnew run (research)
Kimi K2.5Jan 20261.04T / 32B + vision encoderK2, continued with images
Kimi K3Jul 20262.78T / 104Bnew run
GLM (Z.ai)GLM-4.5Jul 2025355B / 32Bnew run
GLM-5, GLM-5.2Feb, Jun 2026744B / 40Bnew run; 5.2 builds on it
GLM-5.3-FlashAug 2026320B / 18Bnew run
MiMo (Xiaomi)MiMo-7BApr 20257B densenew run
MiMo-V2-FlashDec 2025309B / 15Bnew run
MiMo-V2.6 (Pro, Flash)Sep 20261.02T / 42B; 310B / 15Bnew runs
Gemma (Google)Gemma 3Mar 20251B to 27B, densenew run, distilled from a larger teacher
Gemma 4Apr 2026up to 31B dense; one 26B / 3.8B MoEnew run
Gemma 4 12BJun 202612B densenew run, no vision encoder
MAI (Microsoft AI)MAI-Base-1 and MAI-Thinking-1Jun 2026962B / 34.7BBase-1 is the new run; Thinking-1 is its posttrained model
MAI-Base-2Oct 20262.8T / 80Bnew run, not released
Thinking MachinesInklingJul 2026975B / 41Bnew run
Inkling-SmallJul 2026276B / 12Bseparate run
Qwen (Alibaba)Qwen3Apr 2025235B / 22B, plus smaller MoE and dense sizesnew run
Qwen3-NextSep 202580B / 3Bnew run
Qwen3.5, Qwen3.8Feb, Aug 2026397B / 17B; 2.4T / 95Bnew runs
Qwen3.8-Flash-NextAug 2026125B / 6B, plus 51B of n-gram tablesnew run, a preview of Qwen's next architecture
MiniMaxMiniMax-Text-01Jan 2025456B / 45.9Bnew run
MiniMax-M2Oct 2025229.9B / 9.8Bnew run
MiniMax-M3, M3.1-FlashJun, Oct 2026about 428B / 23Bnew run; M3.1-Flash builds on it
StepFunStep-3Jul 2025321B / 38B, incl. a 5B vision encodernew run
Step 3.5 FlashFeb 2026196B / 11Bnew run
Step 5 PreviewOct 2026600B / 27Bnew run
Ling (Ant)Ling 2.0 (largest: Ling-1T)Sep, Oct 20251T / 51Bnew runs
Ling-2.5-1T, Ling-2.6-1TFeb, Apr 20261T / 63BLing-1T, attention replaced by continued training
Ling-3.0-flashAug 2026124B / 5.1Bnew run
Nemotron (NVIDIA)Nemotron-HMar 202556B and 8B, densenew runs
Nemotron Nano 2Aug 202512B densenew run
Nemotron 3 Nano, Super, UltraDec 2025; Mar, Jun 202631.6B / 3.2B; 120.6B / 12.7B; 550B / 55Bnew runs
Nemotron 3.5 LightningAug 202630B / 3BNemotron 3 Nano base, distilled from Super's base
MistralMistral Small 3Jan 202524B densenew run
Mistral Large 3, Small 4Dec 2025, Mar 2026675B / 41B; 119B / 6Bnew runs (Small 4 inferred: no earlier Mistral model has its shape)
Ministral 3Dec 20253B to 14B, densepruned from Small 3.1, then distilled from it
OpenAIgpt-oss-120b, gpt-oss-20bAug 2025117B / 5.1B; 21B / 3.6Bnew run
MetaLlama 4 Scout, MaverickApr 2025109B / 17B; 400B / 17Bnew runs; Maverick distilled from Behemoth (about 2T / 288B, previewed only)
Muse GlimmerAug 2026about 30B densenew run, distilled from Muse Spark (a closed model)
Muse Spark OpenOct 2026816B / 42Bopen version of Muse Spark

Dates, sizes and lineage come from the labs' own model cards and reports; the atlas links each source.

How to read these notes

Chapters 00 and 01 set up the cost model that the rest of the notes rely on, so read them first. After that, the chapters stand on their own. The calculator after chapter 03 lets you compare the memory needs of real models at any context length. For which lab adopted what and when, see the pretraining section of the atlas; for what happens after pretraining, see the midtraining and posttraining notes.

00 The two bills: training compute and inference memory

How many floating-point operations did it take to train DeepSeek-V3, how much memory does one 128K-token conversation take on GLM-4.5, and why did the second number start to drive model design in 2025-26?

Two bills

A model is paid for twice: once to train it, a bill counted in floating-point operations (FLOPs) and GPU-hours, and again for every token it serves. Training cost grows with the parameters each token touches and the number of training tokens. Serving cost at long context grows mostly with the bytes kept in memory and read back for every new token.

Training: from 6ND to context-driven cost

How much compute does training take? A good first answer counts how often each weight is used. For every token, each weight matrix takes part in three matrix products: one on the way forward and two on the way back.

StepProductWhat it is forFLOPs per parameter
Forwardy = xWcompute the layer's output2
Backward: weight gradient∂ℒ/∂W = x⊤ · ∂ℒ/∂yhow each weight should change2
Backward: input gradient∂ℒ/∂x = ∂ℒ/∂y · W⊤pass the error signal to the layer below2
Total6

Each product costs 2 FLOPs per weight: one multiply and one add. So every parameter costs about 6 FLOPs per training token, and a model with Na active parameters trained on D tokens costs

Ctrain ≈ 6 · Na · D  =  2·Na·D (forward) + 4·Na·D (backward)

The Chinchilla paper uses this formula as its compute budget. Inference runs only the forward pass, so serving a token costs about 2·Na FLOPs, a third of training.

The count that matters is the parameters that actually multiply the token. In a dense model that is all of them. A mixture-of-experts (MoE) model splits each feed-forward block into E experts, and a router sends each token to only k of them (chapter 02). Unchosen experts do no arithmetic for that token, so FLOPs follow the active parameters Na: the attention and output-head weights, any shared experts (experts every token uses; chapter 02) and the k chosen experts. The input embedding is a table lookup that costs no FLOPs, although some labs include it in their reported active counts. The total N matters for memory.

Worked example: DeepSeek-V3's training bill

DeepSeek-V3 has 671B total parameters, 37B active per token, pre-trained on 14.8T tokens.

C ≈ 6 × (37 × 109) × (14.8 × 1012) ≈ 3.29 × 1024 FLOPs

The report gives 180K H800 GPU-hours per trillion tokens, so 180K × 14.8 = 2,664K GPU-hours of pre-training; with 119K for context extension and 5K for post-training the total is 2.788M. Pre-training lasted 2.664 × 106 × 3,600 = 9.59 × 109 GPU-seconds, so each GPU sustained 3.29 × 1024 / 9.59 × 109 ≈ 3.4 × 1014 FLOP/s, about 343 TFLOP/s. Counting all 671B parameters as active would give 5.96 × 1025 FLOPs, 18 times more.

Cross-check: Llama 4 Maverick has 17B active parameters, saw ~22T tokens and used 2.38M H100 GPU-hours: 6 × 17 × 109 × 22 × 1012 = 2.24 × 1024 FLOPs over 8.57 × 109 GPU-seconds, about 262 TFLOP/s per GPU. Two labs and two GPU types give rates of the same size, so 6NaD works as a budget estimate.

What 6ND leaves out. A transformer does two kinds of work for each token:

  • Applying the learned weights. The token's vector is multiplied by weight matrices. This costs the same whether the context holds 10 tokens or 10,000, about 2Na FLOPs per token in the forward pass, and it is all that 6ND counts.
  • Attention. The token compares itself with the tokens before it: about 10 comparisons with 10 earlier tokens, about 10,000 with 10,000. This work grows with the context but adds no parameters, so a parameter count cannot see it.

For a standard dense transformer with L layers of width d, Kaplan et al. write the forward cost per token as two terms, with n the context length:

24·L·d2 (applying the weights)  +  2·L·n·d (attention over n tokens)

Their ratio says when attention matters:

2·L·n·d / 24·L·d2  =  n / 12d

When the context is short next to the width, attention is a small add-on. At d = 4,096 and 8K tokens it is about 17% of the weight work, which is why Kaplan et al. drop it when d > n/12. At 128K tokens the same model spends 2.7 times as much on attention as on its weights, and at 1M about 21 times. The parameter count did not change; the context did. So 6ND is a good budget for pretraining at short context and a poor one for long-context training and serving, the subject of chapter 03.

applying the weights 86%attention 14%

n/12d = 0.17: attention adds 17% on top of the weight work. 6ND counts only the blue part.

Share of the compute per token in a standard dense transformer. The number of layers cancels, so only d and n matter; the backward pass roughly triples both parts, so training has the same split.

Where do 24Ld2 and 2Lnd come from?

Weights. A standard layer has 12d2 weights: the query, key, value and output projections (4d2) and an MLP that widens d to 4d and back (8d2). So N ≈ 12Ld2, and applying them costs 2N ≈ 24Ld2 FLOPs per token. The 12 comes from this layer shape; models with grouped-query attention, a different MLP width or mixture-of-experts layers have a different constant.

Attention. One query–key dot product costs 2d FLOPs. Done against n keys in each of L layers, that is 2Lnd per token. Kaplan's term counts only these scores; in causal training, mixing the values roughly doubles the work and the mask roughly halves it, so 2Lnd stays a fair estimate.

Inference: prefill and decode

A model writes one token at a time. In every layer, each new token attends to all the tokens before it: its query is compared with their keys, and their values are mixed according to the scores. Serving runs in two phases, which Pope et al. call prefill and decode:

  • Prefill pushes all prompt tokens through the network together, so each weight matrix multiplies a large block of activations.
  • Decode generates one token per step, since each step needs the previous one's output.

Both spend about 2·Na FLOPs per token on weights. What separates them is how many bytes each step has to read, and most of those bytes come from the KV cache.

The KV cache

The earlier tokens do not change while the model writes, so neither do their keys and values. Recomputing them at every step would repeat the same work, so servers keep them in memory instead. That store is the KV cache. In each layer, a decode step does three things (Figure 0.1):

  1. computes the new token's query, key and value;
  2. scores the query against every cached key and mixes the cached values by the resulting weights;
  3. appends the new key and value to the cache.
One decode step in one layer One decode step in one layer 1 Compute new token's hidden state q k v for every head 2 Attend: score q against every cached key, then mix the cached values cached keys wₛ = softmax(q · kₛ) cached values k₁ v₁ k₂ v₂ … … kₙ vₙ output = Σₛ wₛ vₛ 3 Append the new k and v (outlined) join the cache: one more entry per token, in every layer Without the cache, step 2 would first recompute the key and value of every earlier token, in every layer, at every step.
Figure 0.1. One decode step in one layer. The green bars are the attention weights: one score per cached key, turned into weights by a softmax. The output mixes every cached value, so step 2 reads the whole cache.

The cache trades computation for memory, and the memory has two costs:

  • Capacity. The cache grows by one entry per token in every layer and must fit in GPU memory beside the weights, so it limits how many conversations a server can hold.
  • Bandwidth. Step 2 reads the whole cache again for every generated token, so the bytes moved per step grow with the context.

Its size follows from what each layer stores: one key and one value for each key/value head.

KV bytes per token = 2key and value × Llayers × hkvKV heads × dhnumbers per head × bbytes per number

A sequence of n tokens needs n times that, and a batch of B sequences B times more. With easy numbers, 32 layers, 8 KV heads of 128 numbers and 2-byte bfloat16 give 2 × 32 × 8 × 128 × 2 = 131,072 bytes (128 KiB) per token: 1 GiB at 8,192 tokens and 16 GiB at 131,072.

The formula counts KV heads hkv, not query heads h. The original transformer gave every query head its own key/value head, and for a 500B+ model laid out that way, Pope et al. find that batch 512 at context 2,048 needs a 3 TB cache, three times the parameters. Multi-query attention shares one key/value head across all query heads, and grouped-query attention (GQA) uses an intermediate number of key/value heads, so each cached head serves h/hkv query heads and the cache shrinks by that factor. Chapter 03 covers designs that shrink it further.

One decode step in code
def decode_step(x, cache, layers):            # x: [d], the newest token's hidden state
    for l, layer in enumerate(layers):
        u = rmsnorm(x)
        q = (u @ layer.W_q).reshape(h, d_h)     # [h, d_h]   (RoPE omitted)
        k = (u @ layer.W_k).reshape(h_kv, d_h)  # [h_kv, d_h]
        v = (u @ layer.W_v).reshape(h_kv, d_h)  # [h_kv, d_h]
        cache.K[l].append(k)                    # cache grows by 2*h_kv*d_h numbers
        cache.V[l].append(v)
        K = stack(cache.K[l])                   # [n, h_kv, d_h]: all n tokens are read
        V = stack(cache.V[l])                   # [n, h_kv, d_h]
        g = h // h_kv                           # query heads per KV head
        heads = []
        for i in range(h):
            j = i // g                          # the KV head this query head uses
            scores = K[:, j, :] @ q[i] / sqrt(d_h)   # [n], one per key position s
            heads.append(softmax(scores) @ V[:, j, :])  # [d_h]
        x = x + concat(heads) @ layer.W_o       # [d]
        x = x + layer.ffn(rmsnorm(x))           # dense FFN or MoE
    return x

Why decode is limited by memory bandwidth

Caching saves recomputation, but every generated token must read the whole accumulated cache. Whether that matters depends on how fast a chip reads memory compared with how fast it does arithmetic. Dividing one by the other gives the FLOPs each byte read from high-bandwidth memory (HBM) must feed to keep the chip busy. A TPU v4 chip does 275 TFLOPS of bfloat16 matrix arithmetic and reads 1,200 GB/s, about 229 FLOPs per byte. An H100 SXM does 989 TFLOPS of dense 16-bit matrix arithmetic and reads 3.35 TB/s, about 295.

  • Weights are shared. A 2-byte weight read once and applied to B tokens does 2B FLOPs, B per byte. Prefill applies each weight to thousands of prompt tokens, so it keeps the chip busy and is compute-bound. Decode has one token per sequence, but batching B sequences lets one read serve B tokens.
  • The cache is not. Each sequence's keys and values serve only that sequence, so batching does not help. With GQA each cached number feeds h/hkv query heads at 2 FLOPs each, far below the 229 to 295 a chip needs per byte.

So decode is usually memory-bandwidth-bound: the bytes read per step set its speed, and at long context most of those bytes are cache (Figure 0.2). That is the common case rather than a law. A large batch of short sequences can push decode back toward compute, and some attention designs raise the FLOPs per cached byte (chapter 03).

Bytes read per decode step Bytes read per decode step · GLM-4.5 · bfloat16 · to scale active weights, read once for the whole batch KV cache, read once per sequence 1 sequence 8K tokens weights 64 GB cache 3.1 GB 67 GB, 5% cache 32K tokens weights 64 GB cache 12.3 GB 76 GB, 16% cache 128K tokens weights 64 GB cache 49.4 GB 113 GB, 44% cache 8 sequences 8K tokens weights 64 GB cache 24.7 GB 89 GB, 28% cache 32K tokens weights 64 GB cache 98.8 GB 163 GB, 61% cache 128K tokens weights 64 GB cache 395.1 GB 459 GB, 86% cache 0 100 GB 200 GB 300 GB 400 GB 500 GB A batch of sequences routes to more experts than one token does, so the weight bar is a lower bound (up to all 355B parameters).
Figure 0.2. Bytes one decode step reads for GLM-4.5 in bfloat16: 64 GB of active weights plus 368 KiB of cache per token per sequence (the worked example below derives both). Batching shares the weight reads; the cache grows with both batch size and context length.

Worked example: GLM-4.5's cache at 128K tokens

GLM-4.5 uses GQA in all 92 layers, with 96 query heads, 8 KV heads and head dimension 128, in bfloat16 (b = 2):

2 × 92 × 8 × 128 × 2 = 376,832 bytes per token (368 KiB)

At its maximum context of 131,072 tokens that is 376,832 × 131,072 ≈ 49.4 GB for one sequence, 62% of an H100's 80 GB of memory. A server splits both the weights and the cache across its GPUs, but the totals still have to fit: the model has 355B parameters, 32B active, 710 GB in bfloat16, of which each step reads at least the 64 GB active.

Batching does not shrink the cache. With eight sequences a step reads 8 × 49.4 = 395 GB of cache, six times the active weights (Figure 0.2). Each cached number serves 96/8 = 12 query heads at 2 FLOPs each: 24 FLOPs per 2-byte number, or 12 per byte, against the ~295 an H100 needs. Without GQA (hkv = 96) the cache would be 12 times larger, 593 GB per sequence.

In bfloat16 the weights alone overflow eight H100s (8 × 80 = 640 GB). GLM-4.5's model card lists eight H200 GPUs for the full 128K context, with weights and cache in FP8 and at most 8 sequences per batch. FP8 means b = 1, which halves every byte count above. An H200 has 141 GB at 4.8 TB/s. Memory: about 355 GB of weights plus 8 × 24.7 = 198 GB of cache is 553 GB of the 8 × 141 = 1,128 GB. Each step reads at least 32 + 198 = 230 GB, 86% of it cache; at 8 × 4.8 = 38.4 TB/s that takes at least 230 / 38,400 ≈ 6.0 ms, so each sequence gets at most about 167 decode steps per second.

Long contexts also raise compute. Attention for one query costs 4·n·h·dh FLOPs per layer: 2 per number for the q·k scores over n keys and 2 for mixing n values (Kaplan's term counts only the scores). At GLM-4.5's 4,096-token pre-training length that is 4 × 4,096 × 96 × 128 × 92 ≈ 1.9 × 1010 FLOPs for the last token, already 29% of the 2 × 32B = 6.4 × 1010 spent on weights (about 15% on average, since the token at position t sees only t keys). At 131,072 tokens it is 5.9 × 1011, nine times the weights. Kaplan's rule calls this term small because it assumes a dense model whose attention width equals its model width. GLM-4.5's attention width, 96 × 128 = 12,288, exceeds its hidden size of 5,120, and as an MoE it has few active weights per layer.

Why memory became the binding constraint

The training bill is paid once, however long users' conversations later get; the serving bill grows with every token of context. An agent keeps its task, opened files, tool outputs and reasoning in context across many steps, and Kimi K3's report describes training for million-token agentic RL (reinforcement learning on multi-step tool-using tasks, where each rollout keeps the whole session in context). Each session owns a cache that grows linearly with n. Capacity caps how many sessions fit on a server, and so the throughput; bandwidth sets the time per token. The 2025-26 reports name this cause and report cache sizes at 1M tokens.

Many of the later chapters shrink the term 2·L·hkv·dh·b·n: compress each layer's entry (multi-head latent attention, MLA), let most layers see only a recent window, replace the growing cache with a fixed-size state (linear attention), read only selected entries (sparse attention), or store fewer bytes per number. DeepSeek-V3's MLA caches 512 + 64 = 576 numbers per layer per token (a 512-number compressed latent plus a 64-number position key; chapter 03) where GLM-4.5 caches 2 × 8 × 128 = 2,048, so its 128K cache is 61 × 576 × 2 × 131,072 ≈ 9.2 GB instead of 49.4 GB. Hybrids shrink L, the number of layers that keep a cache. Qwen3.5 (397B total) has 60 layers, but only its 15 gated-attention layers cache keys and values, with 2 KV heads of dimension 256; the other 45 are Gated DeltaNet linear-attention layers that keep a fixed state (chapter 03). Its 128K cache is 15 × 2 × 2 × 256 × 2 × 131,072 ≈ 4.0 GB, plus about 94 MB of state (45 layers × 64 heads × 128 × 128 numbers at 2 bytes) that does not grow with n.

Who uses it and why

"Concurrently, the emergence of long-horizon scenarios and tasks — from complex agentic workflows to massive cross-document analysis — has also made efficient support for ultra-long contexts critical for future progress."

"The widespread adoption of long-horizon agents has made model workloads increasingly input-heavy. Although prior work has substantially reduced the cost of long-context computation, prefill remains computationally expensive, and large KV caches continue to strain HBM and SSD capacity and data-transfer bandwidth."

"Kimi Linear outperforms full MLA with a sizeable margin across all evaluated tasks, while reducing KV cache usage by up to 75% and achieving up to 6× decoding throughput for a 1M context."

Trade-offs

  • 6·Na·D leaves out attention arithmetic, which grows with training context length (about 15% extra for GLM-4.5 at 4,096 tokens), and says nothing about hardware efficiency. Turning FLOPs into GPU-hours needs a sustained-rate estimate such as the 260-340 TFLOP/s above.
  • Fewer KV heads cost some quality: multi-query attention reports minor quality degradation, and GQA aims for quality close to multi-head attention.
  • A smaller cache allows bigger batches, until weight reads, expert routing or GPU-to-GPU traffic become the limit.

Takeaways

  • Training compute is about 6·Na·D: 3.3 × 1024 FLOPs for DeepSeek-V3, which matches its 2.664M pre-training GPU-hours at about 343 TFLOP/s per GPU.
  • Decode is limited by bytes read per step: the weights once per batch, plus each sequence's whole KV cache of 2·L·hkv·dh·b·n bytes.
  • At 128K to 1M tokens the cache rivals the weights (49.4 GB per 128K sequence for GLM-4.5), so 2025-26 designs concentrate on shrinking it.
Check yourself: gpt-oss-120b has 36 layers with 8 KV heads of dimension 64, and 18 of them attend only to the last 128 tokens. How large is its BF16 cache for one 131,072-token sequence, and what if all 36 layers attended to everything?

Per token per layer: 2 × 8 × 64 × 2 = 2,048 bytes. Full layers: 18 × 2,048 × 131,072 ≈ 4.83 GB; windowed layers: 18 × 2,048 × 128 ≈ 4.7 MB; total ≈ 4.84 GB. All-full would be 36 × 2,048 × 131,072 ≈ 9.66 GB. (From the gpt-oss-120b config.json.)

Check yourself: why does batching more users speed up the weight reads of decode but not the KV-cache reads?

One read of a shared weight matrix serves all B tokens in the step. Each sequence has its own keys and values, so doubling the batch doubles the cache bytes read while the cache's FLOPs per byte stay fixed.

  1. Kaplan et al., Scaling Laws for Neural Language Models (2020), §2.1 and Table 1
  2. Hoffmann et al., Training Compute-Optimal Large Language Models (Chinchilla, 2022), §3.3
  3. Pope et al., Efficiently Scaling Transformer Inference (2022), §2 and §4
  4. Shazeer, Fast Transformer Decoding: One Write-Head is All You Need (2019)
  5. Ainslie et al., GQA: Training Generalized Multi-Query Transformer Models from Multi-Head Checkpoints (2023)
  6. DeepSeek-AI, DeepSeek-V3 Technical Report (2024), §1 Table 1, §4 and DeepSeek-V3 config.json
  7. GLM-4.5 Team, GLM-4.5 report (2025), §1-2 and GLM-4.5 config.json
  8. Meta, Llama 4 model card and Llama 4 blog
  9. NVIDIA H100 product page, technical specifications
  10. DeepSeek-AI, DeepSeek-V4 report (2026), §1
  11. DeepSeek-AI, DeepSeek-V4.1-Flash report (2026), Abstract
  12. Kimi Team, Kimi K3 report (2026), §1
  13. Kimi Team, Kimi Linear report (2025), Abstract
  14. gpt-oss-120b config.json

01 Scale and sparsity

How large are the 2025-26 base models, how much of each one does a single token use, and why were the large MoE bases trained on 20 to 140 times more tokens per active parameter than Chinchilla's compute-optimal ratio for dense models (and small dense models even more)?

Total and active parameters

In a dense transformer every parameter processes every token, so the total count N equals the active count Na. Gemma 3 27B is dense: of its 25,600M non-embedding, 1,416M embedding and 417M vision-encoder parameters, all the non-embedding ones serve each text token (the embedding table is a lookup and the vision encoder runs only on images).

A mixture-of-experts (MoE) model pulls the two counts apart: each feed-forward block becomes E experts, and a router picks k of them per token (chapter 02), what Shazeer et al. called conditional computation, where parts of the network are active on a per-example basis. More experts raise N; Na depends only on k and the expert size.

A toy with easy numbers shows how far apart they can drift: 4B of shared weights (attention and the other non-expert layers) that every token uses, and 96B of experts, 64 per layer, with k = 4 per layer.

N = 4B + 96B = 100B      Na = 4B + 96B × 4/64 = 10B

Doubling the experts to 128 per layer, each the same size, makes the total 4B + 192B = 196B, while a token still uses 4B + 192B × 4/128 = 10B.

The ratio of the two counts is the active share:

active share = Naused per token / Nheld in memory

It is 100% for a dense model and falls from 10% to 10/196 ≈ 5.1% as the toy's experts double. The two counts pay for different things (chapter 00):

  • Active parameters pay for compute. The training bill is 6·Na·D for D training tokens, and serving costs 2·Na FLOPs per token.
  • Total parameters pay for memory and capacity. Any token may be routed to any expert, so all N must stay loaded: the toy's doubling takes its bfloat16 weights from 200 GB to 392 GB at the same FLOPs. In return, Kimi's K2 report finds that at a fixed active count, more experts lower the loss (quoted below).

Capacity is bought with memory rather than compute, which is why totals can grow much faster than active counts.

An MoE feed-forward block in code
def moe_ffn(x, router, experts, k):          # x: [d], one token's hidden state
    scores = router(x)                         # [E], one score per expert
    top = argsort(scores)[-k:]                 # the k highest-scoring experts
    w = softmax(scores[top])                   # [k] mixing weights (one common choice)
    y = zeros_like(x)
    for wi, e in zip(w, top):                  # only k of the E experts run, so the
        y += wi * experts[e](x)                # token pays FLOPs for k experts, not E
    return y                                   # but all E experts must stay in memory

How sparse the 2025-26 bases are

Real bases sit near or below the doubled toy's 5.1%. DeepSeek-V3 runs 37B of 671B per token (5.5%), gpt-oss-120b 5.13B of 116.83B (4.4%), Kimi K3 104.2B of 2.78T (3.7%) and Kimi K2 32.6B of 1.04T (3.1%). Kimi K2 in bfloat16 needs 1.04T × 2 bytes ≈ 2.1 TB for its weights while doing the arithmetic of a 32.6B dense model.

In Figure 1.1, read each outline as memory and its filled sliver as compute per token: the totals run from 27B to 2.78T, while the MoE active counts stay between 5B and 41B, Kimi K3's 104.2B aside.

Total vs active parameters Total vs active parameters · billions · one linear scale total parameters (held in memory) active per token (sets FLOPs) total · active · share Gemma 3 27B Gemma 3 27B: 27B total Gemma 3 27B: 27B, drawn as fully active (dense); 25.6B non-embedding per text token 27B · 27B · 100.0% gpt-oss-120b gpt-oss-120b: 116.83B total gpt-oss-120b: 5.13B active 116.83B · 5.13B · 4.4% MiMo-V2-Flash MiMo-V2-Flash: 309B total MiMo-V2-Flash: 15B active 309B · 15B · 4.9% GLM-4.5 GLM-4.5: 355B total GLM-4.5: 32B active 355B · 32B · 9.0% Llama 4 Maverick Llama 4 Maverick: 400B total Llama 4 Maverick: 17B active 400B · 17B · 4.2% DeepSeek-V3 DeepSeek-V3: 671B total DeepSeek-V3: 37B active 671B · 37B · 5.5% Inkling Inkling: 975B total Inkling: 41B active 975B · 41B · 4.2% Kimi K2 Kimi K2: 1040B total Kimi K2: 32.6B active 1,040B · 32.6B · 3.1% Kimi K3 Kimi K3: 2780B total Kimi K3: 104.2B active 2,780B · 104.2B · 3.7% 0B 500B 1,000B 1,500B 2,000B 2,500B
Figure 1.1. Total parameters (outline) and active parameters per token (fill) on one linear scale. Totals follow the grid's convention of leaving out separate vision or audio encoders unless the lab counts them; Gemma 3 27B's 27B includes its vision encoder and is drawn as fully active, as for any dense model, although only its 25.6B non-embedding parameters serve each text token (see text); Kimi K3 uses its report's Table 1 figure of 2.78T. Sources: the labs' reports and cards, as cited in the text and in the pretraining section of the atlas.

Beyond these nine, every new base above 32B parameters in the grid these notes were first written from uses experts. Of its 31 new pretraining runs, 21 are MoE, 3 mix dense and MoE layers, and the 7 dense ones have at most 32B parameters. Among the labs added later, the one exception is NVIDIA's Nemotron-H-56B (Mar 2025), which has no experts: about 8% of its layers are attention, and the rest alternate Mamba-2 state-space layers (chapter 03) with dense feed-forward layers.

Compute-optimal: about 20 tokens per parameter

How long should a model train? For dense models the question is how to split a fixed training budget C ≈ 6ND between parameters and tokens.

The Chinchilla paper (Hoffmann et al., 2022) trained over 400 models from 70M to over 16B parameters and concluded that for every doubling of model size the number of training tokens should also be doubled: its three methods give N and D each growing as about C0.5, so doubling the budget scales both by √2 ≈ 1.4 and keeps their ratio. Kaplan et al. had found the optimal model size growing as C0.73 and the tokens as C0.27, which put most extra compute into larger models. The paper's Table 3 puts a 1B model at 20.2B tokens and a 10B model at 205.1B, about 20 tokens per parameter, and Chinchilla itself, 70B parameters on 1.4T tokens, sits at exactly 20.

Compute-optimal answers one question: the lowest training loss for a given training budget. It counts nothing that happens after training, and it was fitted on dense models. The next section adds both.

Over-training on purpose

Sardana et al. add the serving bill. A model trained on Dtrain tokens and then used on Dserve tokens costs

Ctotal = 6 · N · Dtraintraining, paid once + 2 · N · Dserveserving, grows with every user

If Dserve = 10Dtrain, for example, serving costs 20 · N · Dtrain, over three times the training bill. When Dserve is large, a smaller N trained on more tokens reaches the same loss for less total compute, even though its training run alone is less efficient. Sardana et al. conclude that labs expecting large demand should train models smaller and longer than Chinchilla-optimal, and their models kept improving up to 10,000 tokens per parameter. LLaMA made the same case in 2023: a smaller model trained longer will ultimately be cheaper at inference.

Experts strengthen the argument. In an MoE model both terms scale with Na, so a lab can keep Na small for cheap tokens, grow the total for capacity, and train on as many tokens as its data supports. The ratio to watch is therefore D/Na, tokens per active parameter. Chinchilla's 20 was fitted on dense models and no comparable value is established for MoE models, so the multiples of 20 below are a rough guide to how far labs go past the dense rule, not an exact measure of over-training.

The lifetime bill in code
def lifetime_flops(N_a, D_train, D_serve):     # Sardana et al., with N replaced by N_a
    return 6 * N_a * D_train + 2 * N_a * D_serve

Worked example: tokens per active parameter

Each row divides a lab's stated pre-training tokens by its active count and compares the result with Chinchilla's 20.

ReleaseDNaD / Na× Chinchilla's 20
DeepSeek-V314.8T37B14.8 × 1012 / 37 × 109 = 40020
Kimi K215.5T32.6B15.5 × 1012 / 32.6 × 109 ≈ 47524
Llama 4 Maverick~22T17B22 × 1012 / 17 × 109 ≈ 1,29465
DeepSeek-V4.1-Flash45T16B45 × 1012 / 16 × 109 ≈ 2,813141

At Chinchilla's dense ratio, DeepSeek-V3 would have stopped at 20 × 37B = 0.74T tokens; it trained on 20 times that. V4.1-Flash's 16B is its decode-time count. Its causal encoder-decoder layout lets it compute only the first half of its layers when it processes a prompt, so it activates 8B during prefill (chapter 13).

The same choice from the other side: V3's budget was 3.29 × 1024 FLOPs (chapter 00). A dense model sized by the Chinchilla rule (D = 20N) for that budget satisfies 6 · N · 20N = C, so N = √(C/120) ≈ 165B parameters on 3.3T tokens. Serving it costs 2 × 165B ≈ 3.3 × 1011 FLOPs per token; V3 costs 2 × 37B = 7.4 × 1010, 4.5 times less, and pays instead by keeping 671B parameters in memory.

Figure 1.2 widens this to twelve releases on a log scale: the MoE bases sit 20 to 140 times past Chinchilla's dashed 20, and the small dense Gemma 3 270M far beyond, at 22,222.

Tokens per active parameter Training tokens per active parameter · D / Nₐ · log scale dense compute-optimal MoE (active parameters) dense Chinchilla 70B (2022) Chinchilla 70B (2022): 20 tokens per active parameter 20 DeepSeek-V3 DeepSeek-V3: 400 tokens per active parameter 400 Kimi K2 Kimi K2: 475 tokens per active parameter 475 Gemma 3 27B Gemma 3 27B: 519 tokens per active parameter 519 MAI-Base-2 MAI-Base-2: 625 tokens per active parameter 625 GLM-5 GLM-5: 675 tokens per active parameter 675 GLM-4.5 GLM-4.5: 688 tokens per active parameter 688 Inkling Inkling: 1,098 tokens per active parameter 1,098 Llama 4 Maverick Llama 4 Maverick: 1,294 tokens per active parameter 1,294 MiMo-V2-Flash MiMo-V2-Flash: 1,800 tokens per active parameter 1,800 DeepSeek-V4-Flash DeepSeek-V4-Flash: 2,462 tokens per active parameter 2,462 DeepSeek-V4.1-Flash DeepSeek-V4.1-Flash: 2,813 tokens per active parameter 2,813 Gemma 3 270M Gemma 3 270M: 22,222 tokens per active parameter 22,222 10 100 1,000 10,000 100,000
Figure 1.2. Pre-training tokens per active parameter, log scale; the dashed line marks Chinchilla's dense-model 20. D is each lab's stated pre-training total. For Kimi K2, MiMo-V2-Flash and DeepSeek-V4/V4.1 it includes stages this report maps to mid-training (continued pretraining on a re-weighted mix, such as more code, math or long documents, between the main run and post-training); for Llama 4, Inkling, V4.1-Flash and Gemma 3 it includes image or other multimodal tokens. DeepSeek-V4.1-Flash uses its 16B decode-time active count. Values from the pretraining grid in the atlas.

New bases and refreshes

Releases come in two kinds:

  • A new pretraining run trains a base from scratch and pays the whole training bill. DeepSeek-V3's pre-training took 2,664K of its 2,788K GPU-hours; post-training took 5K.
  • A refresh starts from an existing base, changing only post-training or continuing its pretraining.

Labs therefore train bases rarely and release on top of them often. Of the 68 releases in that grid, 31 are new pretraining runs; 19 change only post-training, 10 continue pretraining an existing base, 2 are speculative-decoding drafters, 1 is a distilled student and 5 do not say. A drafter is a small model that proposes tokens for the large one to check (chapter 06); a distilled student is trained to imitate another model's outputs (chapter 12).

DeepSeek-V3's base, released in December 2024, carried nine more releases up to V3.2 in December 2025. Two of them added continued pretraining: 840B tokens of long-context training for V3.1, 5.7% of the base's 14.8T, and a phase that added sparse attention for V3.2-Exp. A refresh can change data, context length and even attention, but it keeps the base's N and Na.

Who uses it and why

"In MoE models, a single token activates only a fraction of the total parameters. MoE architectures are more compute efficient for training and inference and, given a fixed training FLOPs budget, delivers higher quality compared to a dense model."

"we observe that — under a fixed number of activated parameters (i.e., constant FLOPs) — increasing the total number of experts (i.e., increasing sparsity) consistently lowers both the training and validation loss, thereby enhancing overall model performance"

"Meanwhile, its small activation footprint yields low inference latency and serving cost."

Trade-offs

Takeaways

  • FLOPs follow active parameters; memory and capacity follow total parameters. The large MoE bases in Figure 1.1 activate about 3-9% of their weights per token.
  • Chinchilla's ~20 tokens per parameter, fitted on dense models, minimizes training compute only. Once serving is counted, labs train far longer: about 400 to 2,800 tokens per active parameter for the MoE bases in Figure 1.2, a rough comparison since the MoE optimum is not known.
  • New bases are rare and costly: 31 of 68 releases are new runs, and the DeepSeek-V3 base carried nine later releases. A refresh keeps its base's N and Na.
Check yourself: Kimi K2 has 1.04T total and 32.6B active parameters and was pre-trained on 15.5T tokens. Roughly how many training FLOPs is that, and how much memory do its weights take in bfloat16?

6 × 32.6 × 109 × 15.5 × 1012 ≈ 3.0 × 1024 FLOPs, close to DeepSeek-V3's 3.3 × 1024. Weights: 1.04 × 1012 × 2 bytes ≈ 2.1 TB, about 1.5 times V3's 1.34 TB, even though its per-token arithmetic is slightly smaller.

Check yourself: DeepSeek-V3 and a 165B dense model trained on 3.3T tokens cost the same to train. Ignoring quality differences, after how many served tokens has V3 saved compute equal to its whole training budget?

Each served token saves 2 × (165 − 37) × 109 ≈ 2.6 × 1011 FLOPs. Dividing the budget, 3.29 × 1024 / 2.6 × 1011 ≈ 1.3 × 1013: about 13T served tokens, less than its own training set.

  1. Shazeer et al., Outrageously Large Neural Networks: The Sparsely-Gated Mixture-of-Experts Layer (2017)
  2. Kaplan et al., Scaling Laws for Neural Language Models (2020)
  3. Hoffmann et al., Training Compute-Optimal Large Language Models (Chinchilla, 2022), Abstract, Tables 2-3
  4. Sardana et al., Beyond Chinchilla-Optimal: Accounting for Inference in Language Model Scaling Laws (2024)
  5. Touvron et al., LLaMA: Open and Efficient Foundation Language Models (2023), §1
  6. DeepSeek-AI, DeepSeek-V3 Technical Report (2024)
  7. Kimi Team, Kimi K2 report (2025) and Kimi K3 report (2026)
  8. OpenAI, gpt-oss-120b and gpt-oss-20b model card (2025)
  9. Gemma Team, Gemma 3 Technical Report (2025)
  10. Meta, Llama 4 blog and Llama 4 model card
  11. DeepSeek-AI, DeepSeek-V4.1-Flash report (2026) and DeepSeek-V4 report (2026)
  12. DeepSeek-AI, DeepSeek-V3.2-Exp report (2025) and DeepSeek-V3.1 release note
  13. Other token and parameter counts in Figures 1.1-1.2: GLM-4.5, GLM-5, MiMo-V2-Flash, Inkling, MAI-Base-2, Gemma 3 model card (270M)
  14. Atlas, pretraining section (coded grid of 68 releases)
  15. NVIDIA, Nemotron-H report (2025)

02 Inside a mixture-of-experts layer

How can DeepSeek-V3 store 671B parameters but run only 37B of them for each token, and what keeps its 256 experts evenly used?

From one feed-forward block to many experts

A transformer block has two parts: attention, where tokens read each other (chapter 03), and a feed-forward network (FFN), which transforms each token on its own. A standard block sends every token through the same FFN, so every FFN weight works on every token. DeepSeek-V3's FFN is a SwiGLU block with three matrices and 3 · d · dff weights, for model width d and inner width dff.

The SwiGLU block in symbols
FFN(u) = Wdown ( SiLU(Wgate u) ⊙ Wup u ),    SiLU(z) = z · σ(z)      u ∈ ℝd;  Wgate, Wup ∈ ℝdff×d;  Wdown ∈ ℝd×dff

The gate branch decides, channel by channel, how much of the up branch passes through.

A mixture-of-experts (MoE) layer replaces that FFN with E smaller FFNs, called experts, and a router that sends each token to k of them:

  • Memory follows E. Every expert is stored, used or not.
  • Compute follows k. A token is multiplied only by the experts it visits.

That is how DeepSeek-V3 holds 671B parameters in total (N) but runs 37B per token (Na).

One token through the layer

The router holds one learned vector ei ∈ ℝd per expert and takes four steps for each token u:

  1. Score the token against every expert: si = σ(u⊤ei), i = 1…E. DeepSeek-V3 uses this sigmoid; Switch Transformer used a softmax.
  2. Choose the k best: Top(u) = TopK({si + bi}, k). Switch used k = 1 and GShard top-2 gating. The bias bi is DeepSeek-V3's balancing term, explained below.
  3. Weight each chosen expert by its share of the chosen scores: gi = si / ∑j∈Top(u) sj.
  4. Combine the gated expert outputs with the Ns shared experts, which every token uses without routing, and the residual input u:
h′ = uresidual + ∑j=1…Ns FFN(s)j(u)shared experts, no gate + ∑i∈Top(u) gi · FFN(r)i(u)k routed experts, gated

with u, h′ ∈ ℝd, s, b ∈ ℝE and |Top(u)| = k. The gate is what trains the router: each chosen expert's output is scaled by its score, so the loss gradient can raise or lower that score. Figure 2.1 draws the same steps for one token.

Data flow through one mixture-of-experts layer residual: + u token u d = 7168 router scores s + b, keep top k routed experts (E in total) filled: the k experts this token uses × gate gᵢ shared expert: every token, no gate Σ h′ Drawn with E = 16 and k = 3 for legibility. DeepSeek-V3: E = 256 routed, k = 8, one shared expert.
Figure 2.1. One MoE layer, one token. The bias b only decides which k experts run; their outputs are weighted by gates gi from the unbiased scores and added to the shared expert and the residual.

A toy layer. Take E = 4 routed experts, k = 2 and four tokens, with no bias yet:

TokenScores s, experts 1–4Top 2Gates
A0.9, 0.6, 0.2, 0.11, 20.6, 0.4
B0.6, 0.1, 0.4, 0.11, 30.6, 0.4
C0.4, 0.6, 0.1, 0.32, 10.6, 0.4
D0.3, 0.1, 0.7, 0.23, 10.7, 0.3

A's gates are 0.9/1.5 and 0.6/1.5. Each token runs two of the four stored experts. Now count the load: expert 1 gets all four tokens and expert 4 none, where a fair share is 4 × 2/4 = 2 each.

More, smaller experts, plus a shared one

Early MoE layers used a few large experts, often 8 or 16. The DeepSeekMoE paper (2024) argued that each such expert must store mixed knowledge, while knowledge that every token needs gets copied into many experts. It proposed two fixes:

  • Fine-grained segmentation splits each expert into several narrower ones (the paper's example uses 4, each a quarter as wide) and activates proportionally more of them, so parameters and compute stay fixed while the number of expert combinations explodes: top-2 of 16 experts allows 120, top-8 of 64 allows 4,426,165,368.
  • Shared expert isolation adds experts that every token uses without routing, to hold the common knowledge.

DeepSeek-V3 has 256 routed experts of width 2048, 8 active per token, and 1 shared expert.

Keeping the load even

Nothing in the language-modeling loss spreads tokens out, and imbalance like the toy's costs twice:

  • Quality. Experts that win early get more gradient and win more, while the rest starve: routing collapse.
  • Speed. The GPU holding a popular expert makes the others wait.

An auxiliary loss is the classic fix. Switch Transformer adds

αstrength · Eexperts · ∑i fishare of tokens sent to i · Pimean router probability of i

which is smallest under uniform routing, with α = 10−2. Wang et al. (2024) showed the bind: a small α lets routing collapse, and a large α adds gradients that conflict with language modeling and hurt perplexity.

A routing bias, their auxiliary-loss-free method, adds a per-expert bias bi to the scores only when choosing the top k. Gates use the raw scores, so the bias changes which experts run but leaves the output weights and gradients alone. After each step an overloaded expert's bias falls by γ and an underloaded one's rises by γ. The update uses only the finished batch, so no routing decision depends on future tokens.

In the toy, one update with γ = 0.2 gives b = (−0.2, 0, 0, +0.2). C's biased scores become (0.2, 0.6, 0.1, 0.5) and D's (0.1, 0.1, 0.7, 0.4), so both swap expert 1 for expert 4 and every expert gets 2 tokens. C's gates still come from its raw scores, 0.6 and 0.3: 2/3 and 1/3.

At 1B parameters this improved validation perplexity from 9.56 to 9.50 and cut MaxVio, the busiest expert's excess over a balanced load, from 0.72 to 0.04.

One MoE layer and the bias update in code
def moe_layer(u, W_r, b, experts, shared, k):
    # u: [B_tok, d] tokens; W_r: [E, d] expert vectors; b: [E] routing bias
    s = sigmoid(u @ W_r.T)                   # [B_tok, E] affinity scores
    top = topk_indices(s + b, k)             # [B_tok, k] bias only picks experts
    g = take_along_axis(s, top, axis=-1)     # [B_tok, k] gates use raw scores
    g = g / g.sum(axis=-1, keepdims=True)    # normalize over the k chosen
    y = shared(u)                            # [B_tok, d] always-on shared expert
    for t in range(len(u)):
        for j in range(k):
            y[t] += g[t, j] * experts[top[t, j]](u[t])
    load = bincount(top.ravel(), minlength=len(b))   # [E] tokens per expert
    return u + y, load

def update_bias(b, load, gamma=1e-3):
    # after the optimizer step; the new b routes the next batch
    return b + gamma * sign(load.mean() - load)      # lift idle, damp busy

DeepSeek-V3 uses γ = 0.001 for the first 14.3T tokens and 0 for the last 500B, plus a sequence-wise loss with α = 0.0001 against extreme imbalance inside one sequence. Balancing at batch level leaves each sequence free to favor the experts for its domain. In DeepSeek's 1B tests validation loss was 2.258 with a sequence-wise loss and 2.253 with the bias or a batch-wise loss. Microsoft AI found the same for MAI-Thinking-1: an f·P auxiliary loss in GShard's form, with f and P counted over the whole global batch (all data-parallel workers and micro-batches) instead of per sequence, matched the loss-free method.

Quantile Balancing. Kimi K3 (2026) raised the count to 896 routed experts and found the fixed step too blunt: a small γ adapts slowly and a large one makes loads oscillate. Quantile Balancing sets each bias in one shot, to the value that would have given that expert exactly its fair share of the batch just routed. In K3's toy example, 8 tokens, 4 experts and k = 1 start with loads (4, 3, 1, 0) and end with 2 each. K3 reads the quantile from per-GPU histograms summed in one all-reduce, applies the bias from the next step, and freezes it at inference.

Where the quantile rule comes from

In a batch of Btok tokens, each expert's fair share is q = Btok · k/E tokens, a fraction k/E of the batch. For every token t the router records its (k+1)-th largest biased score as a cutoff ct: the score an expert must beat to enter that token's top k. Holding the cutoffs fixed, token t picks expert j when st,j + b̂j > ct, that is, when the margin st,j − ct exceeds −b̂j. For exactly a fraction k/E of the margins to exceed −b̂j, −b̂j must be their (1 − k/E) quantile, which gives the minus sign:

b̂j = −quantile1−k/E ( st,j − ct over the batch's tokens t )      b ← b̂ − mean(b̂)      s ∈ ℝBtok×E, c ∈ ℝBtok, b̂ ∈ ℝE

Subtracting the mean shifts all of a token's scores equally, so no top-k choice changes.

How sparse should a layer be?

Kimi K2 defines sparsity as E/k; the toy's is 2. More experts at fixed k cost memory but no extra expert compute per token, and the labs found they pay off:

  • Kimi K2. In small controlled runs with k = 8 and one shared expert, sparsity 48 needed 1.69×, 1.39× and 1.15× fewer FLOPs than sparsity 8, 16 and 32 to reach validation loss 1.5.
  • Microsoft AI saw steady gains from 256 to 1,024 experts at top-8 and chose 512.
  • Qwen went from 128 experts in Qwen3 to 512 in Qwen3-Next and its successors, reporting that with a global load-balancing loss, more expert parameters at a fixed active count steadily lower training loss.
  • Ant set Ling 2.0's 8 of 256 experts with scaling laws that predicted over 7× the efficiency of a dense model, then activated 8 of 512 in Ling 3.0.

A latent MoE makes each expert cheaper by running the routed experts in a narrower space. NVIDIA's LatentMoE in Nemotron 3 Super (Mar 2026) runs them in a 1,024-wide latent space instead of the 4,096-wide hidden state and spends the savings on 512 experts with 22 active. Kimi K3 did the same four months later: it projects each token from width 7,168 down to a 3,584-wide latent vector once, sends that vector to its routed experts, and projects their combined output back up; shared experts keep the full width. Every copy sent to an expert, and every expert's input and output matrix, is half as large, which lets K3 afford 16 of 896.

Model (release)Routed EActive kSharedE/k
DeepSeek-V3 (Dec 2024)2568132
Kimi K2 (Jul 2025)3848148
Qwen3-Next (Sep 2025)51210151
Nemotron 3 Super (Mar 2026)51222123
DeepSeek-V4-Pro (Apr 2026)3846164
MAI-Thinking-1 (Jun 2026)5128064
Kimi K3 (Jul 2026)89616256
Ling-3.0-flash (Aug 2026)5128164

When dense wins

An MoE buys loss per FLOP with memory. Meta's Muse Glimmer (2026) had to fit a 32GB memory budget, so Meta compared ladders (families of models of increasing size built by one rule) for a dense design and two MoE designs with 1 of every 8 or 16 experts active, holding inference memory fixed. At equal memory an MoE token uses only part of the parameters and so costs less compute; within the same GPU-hours the MoE ladders trained on 2,800 and 6,000 tokens per parameter against 550 for dense, and dense was still 2–2.5× more compute-efficient. Meta chose a dense 30B model.

Worked example: how much of DeepSeek-V3's FFN does one token touch?

From config.json: d = 7168, expert width 2048, 256 routed and 1 shared expert, 8 routed per token, 61 layers with the first 3 dense. Each expert has three matrices (gate, up, down).

  • One expert: 3 × 7168 × 2048 = 44,040,192 ≈ 44.0M parameters.
  • One MoE layer: 257 × 44.0M ≈ 11.32B parameters.
  • One token uses 8 + 1 = 9 experts: 9 × 44.0M ≈ 396M, or 9/257 ≈ 3.5% of the layer's FFN weights.
  • That is the compute of a dense SwiGLU 9 × 2048 = 18,432 wide, exactly the width of V3's dense layers (intermediate_size 18432), with 257/9 ≈ 28.6× the weights.
  • Over 61 − 3 = 58 MoE layers, 58 × 11.32B ≈ 656B parameters, about 98% of 671B, sit in experts. A token uses 58 × 396M ≈ 23.0B of them; its other ≈14B active parameters are attention, the dense layers, embeddings and norms.
  • Each layer chooses among C(256, 8) ≈ 4.1 × 1014 expert combinations.

Who uses it and why

"To achieve a better trade-off between load balance and model performance, we pioneer an auxiliary-loss-free load balancing strategy (Wang et al., 2024a) to ensure load balance."

"Though increasing sparsity leads to better performance, this gain comes with increased infrastructure complexity. To balance model performance with cost, we adopt a sparsity of 48 for Kimi K2, activating 8 out of 384 experts per forward pass."

"Scaling curves (Fig 1) demonstrated that within constraints of training compute and parameter size, dense configurations yielded a 2×-2.5× increase in compute efficiency compared to the MoE counterparts."

Trade-offs

  • All E experts must be in memory. DeepSeek-V3 spreads each layer's routed experts over 64 GPUs on 8 nodes and sends each token to at most 4 nodes.
  • Each MoE layer needs all-to-all exchanges to send tokens to their experts and back; more experts means more traffic, the infrastructure cost Kimi K2 cites.
  • Batch-level balance still allows imbalance within a sequence, in small batches and under domain shift at inference. DeepSeek-V3 serves extra copies of busy experts.
  • Kimi K3 reports exploding activations in the routed branch at 896 experts, contained with an extra RMSNorm and a bounded activation (SiTU-GLU).

Takeaways

  • An MoE layer stores E experts and runs k: memory follows E, compute per token follows k.
  • Fine-grained experts balanced by a routing bias in place of a strong balancing loss came from DeepSeek; eight of the fifteen labs in these notes (DeepSeek, Moonshot, Z.ai, Xiaomi, Thinking Machines, StepFun, Ant and NVIDIA; roster in the introduction) now use that bias, and Kimi K3 sets it from quantiles at 896 experts.
  • More experts at fixed k lowers loss per FLOP (1.69× fewer FLOPs at sparsity 48 than at 8 for Kimi K2), but under a tight memory budget dense can win.
Check yourself: why does DeepSeek-V3 add bi when choosing experts but leave it out of the gate?

The gate scales the expert's output. A bias inside it would change what the layer computes and push balancing pressure into the gradients, which is the interference the auxiliary loss caused. Outside the gate, the bias only changes which experts run.

Check yourself: layer A has 64 experts with 8 active, layer B has 384 with 8 active, all the same size. Compare FLOPs per token, expert memory and sparsity.

FLOPs per token are equal, since both run 8 experts. B stores 6× the expert weights. Sparsity is 8 for A and 48 for B. Kimi K2's law says B's design reaches validation loss 1.5 with 1.69× fewer training FLOPs, paid for in memory and communication.

  1. Fedus, Zoph, Shazeer. Switch Transformers: Scaling to Trillion Parameter Models with Simple and Efficient Sparsity (2021)
  2. Lepikhin et al. GShard: Scaling Giant Models with Conditional Computation and Automatic Sharding (2020)
  3. Dai et al. DeepSeekMoE: Towards Ultimate Expert Specialization in Mixture-of-Experts Language Models (2024)
  4. Wang et al. Auxiliary-Loss-Free Load Balancing Strategy for Mixture-of-Experts (2024)
  5. DeepSeek-AI. DeepSeek-V3 Technical Report (2024) and config.json
  6. DeepSeek-AI. DeepSeek-V4 Technical Report (2026)
  7. Kimi Team. Kimi K2: Open Agentic Intelligence (2025)
  8. Kimi Team. Kimi K3: Open Frontier Intelligence (2026)
  9. Microsoft AI. MAI-Thinking-1: Building a Hill-Climbing Machine (2026) and Frontier Pre-training at Microsoft AI
  10. Meta. Muse Glimmer 30B: An On-Device Agentic Model (2026)
  11. NVIDIA. Nemotron 3 Super report (2026) and Nemotron 3 Nano report (2025). Ant. Ling 2.0 report (2025) and Ling-3.0-flash-base card. Qwen. Qwen3-Next blog and Qwen3.8-Flash-Next blog. StepFun. Step 3.5 Flash report (2026).

03 Attention and the KV cache

Why does every token a model has already read cost memory while it generates, and what did the labs change in attention to make 128K to 1M-token contexts affordable?

What a new token keeps and reads

In multi-head attention (MHA), each of h heads has its own queries, keys and values of size dh:

Attention(Q, K, V) = softmax(QK⊤ / √dh) V,    Q, K, V ∈ ℝn×dh per head

Every head caches its own keys and values (hkv = h), so chapter 00's formula becomes

KV-cache bytes = 2key and value × Llayers × hheads × dhnumbers per head × bbytes per number × ntokens

Chapter 00's toy model (32 layers, heads of 128 numbers, bfloat16) with 32 such heads needs 2 × 32 × 32 × 128 × 2 = 524,288 bytes (512 KiB) per token, 64 GiB at 131,072 tokens. That cache costs capacity, since it must sit in GPU memory, and bandwidth, since every new token reads all of it. Each design below changes one thing:

  • What a layer stores per token: GQA and MQA share key/value heads; MLA stores one compressed vector.
  • How many tokens a layer keeps: sliding windows, compressed attention and linear attention.
  • How many entries a new token reads: sparse attention, which saves bandwidth and arithmetic but not capacity.

Share keys and values: MQA and GQA

Multi-query attention (MQA) keeps h query heads but one key/value head shared by all of them, shrinking the cache h-fold with "only minor quality degradation" in Shazeer's tests. Grouped-query attention (GQA) splits the query heads into hkv groups that each share one key/value head; GQA-1 is MQA and GQA-h is MHA. A new token still reads every cached token, but each entry is h/hkv times smaller: in the toy, 16 GiB at 128K with 8 KV heads and 2 GiB with MQA.

GQA's authors converted MHA checkpoints by mean-pooling each group's heads and training for 5% of the original compute. GLM-4.5 uses 96 query and 8 KV heads; gpt-oss uses 64 and 8. StepFun's Step-3 (Jul 2025, 321B) went to the MQA end: its 64 query heads share one key and one value head of dimension 256, and its queries are factorized through a low-rank bottleneck (MFA). Step 3.5 Flash moved to GQA with 8 KV heads.

Figure 3.1 compares what MHA, GQA and MLA keep per token in one layer.

Head sharing in MHA, GQA and MLA, and what each cachesMHAquery heads (h = 8)q1q2q3q4q5q6q7q8kvkvkvkvkvkvkvkvCACHEDper token, per layer: 2·h·dh​DeepSeek-V3 shape as MHA: 32,768GQA (hkv​ = 2)query heads (h = 8)q1q2q3q4q5q6q7q8kv1kv2CACHEDper token, per layer: 2·hkv​·dh​GLM-4.5 (hkv​ = 8, dh​ = 128): 2,048MLAquery heads (h = 8)q1q2q3q4q5q6q7q8kvkvkvkvkvkvkvkvlatent ct​ (dc​)kR​ (dr​)CACHEDdashed: expanded or absorbed, never storedper token, per layer: dc​ + dr​DeepSeek-V3 (512 + 64): 576
Figure 3.1. What each design caches (dashed outline). MLA stores one latent vector and a small rotary key per token; every head's keys and values are derived from them.

Compress keys and values: MLA

Multi-head latent attention (MLA), from DeepSeek-V2, keeps h distinct key and value heads but stores none of them. It compresses each hidden state xt into a short latent vector, from which fixed matrices rebuild every head's keys and values:

ct = WDKVxt ∈ ℝdc,   kt,i = WiUKct,   vt,i = WiUVct   (head i = 1…h)

The cache holds the latent (dc numbers) plus a small position key kR (dr numbers) shared by all heads. A new token still reads every cached token, but each entry shrinks from 2hdh numbers per layer to dc + dr. With DeepSeek-V3's dc = 512 and dr = 64, the toy model would store 576 numbers per layer, 36 KiB per token and 4.5 GiB at 128K, a fourteenth of MHA.

During decoding the keys and values are never rebuilt: the expansion matrices fold into the query and output projections, so all heads read the same cached latents, which DeepSeek calls the MQA mode of MLA. Rotary position embedding (RoPE) would block that folding, hence the separate position key.

The absorbed form

Only ct is cached, and during decoding the expansion need not run. Head i's score is qt,i⊤WiUKcs = (WiUK⊤qt,i)⊤cs, so WUK is "absorbed" into the new query. Values work the same way: with attention weights ats,i, head i outputs WiUV∑sats,ics, and the output projection block WiO multiplies that, so

ut = ∑i WiOot,i = ∑i (WiOWiUV) ∑s≤t ats,ics

WiOWiUV is one matrix computed once, and attention only mixes cached latents.

Why position needs its own key

RoPE breaks the absorption. In brief (chapter 04 has the details), RoPE rotates a query at position t by a matrix Rt and a key at position s by Rs; since Rt⊤Rs = Rs−t, their dot product is q⊤Rs−tk, which depends only on the offset. For MLA keys that gives q⊤Rs−tWUKcs: a rotation between query and WUK that differs for every cached token, so nothing can be absorbed. DeepSeek's decoupled RoPE splits each head's query and key into an unrotated content part and a small rotated part. The rotated key kRs ∈ ℝdr is shared by all heads; each head has its own rotated query part. The score adds the two dot products:

scoret,s,i = ( qC,t,i⊤kC,s,i + qR,t,i⊤kRs ) / √(dh + dr),    kC,s,i = WiUKcs

The content term absorbs WUK as before; the rotary term reads the cached kRs. The cache holds dc + dr numbers per layer.

Absorbed MLA trades memory for arithmetic: every head scores every cached latent over dc + dr dimensions and mixes it over dc, 1,088 multiply-adds per cached token and head in DeepSeek-V3's shape, against 256 for a 128-number MHA head. With 128 heads sharing each 1,152-byte bfloat16 entry, that is about 240 FLOPs per cached byte, against 12 for GLM-4.5 (chapter 00) and near the ~295 an H100 needs, so the head count drives long-context cost.

Kimi K2 kept MLA but used 64 heads instead of DeepSeek-V3's 128: at 128K tokens, doubling heads adds 83% inference FLOPs for only 0.5–1.2% lower validation loss. Mistral Large 3 (Dec 2025) and Small 4 also use MLA-type attention, with latents of 512 and 256 numbers per layer in their configs.

Worked example: KV-cache bytes per token at 128K

n = 131,072 tokens, b = 2 bytes (BF16 assumed; configs do not fix serving precision); KB, MB, GB are powers of 10.

DeepSeek-V3, MLA: dc = 512, dr = 64, L = 61. (512 + 64) × 61 = 35,136 numbers × 2 B = 70,272 B ≈ 70.3 KB per token; × 131,072 ≈ 9.2 GB.

GLM-4.5, GQA: hkv = 8, dh = 128, L = 92. 2 × 8 × 128 × 92 = 188,416 numbers × 2 B ≈ 376.8 KB per token; ≈ 49.4 GB at 128K, 5.4× DeepSeek-V3.

MHA with DeepSeek-V3's shape: h = dh = 128, 61 layers. 2 × 128 × 128 × 61 = 1,998,848 numbers × 2 B ≈ 4.0 MB per token; ≈ 524 GB at 128K, 57× MLA.

Look only nearby: sliding windows and sinks

A sliding-window layer keeps fewer tokens instead of smaller entries: it attends only to the last w tokens, so its cache stops growing at w and each new token reads at most w entries. Older tokens are out of its reach, so models interleave window layers with global (full) layers, in a ratio written local : global. In the toy with 8 KV heads, a 3 : 1 mix with w = 1,024 keeps 4 GiB in its 8 global layers and 96 MiB in its 24 window layers, about 4.1 GiB instead of 16.

  • Gemma 3 uses 5 : 1 (5 local layers per global one) with w = 1024. For a 2B model at 32K tokens, its report shows cache overhead falling from 60% of memory (global only) to under 15% with three local layers per global one and w = 1024.
  • gpt-oss alternates 1 : 1 with w = 128.
  • MiMo-V2-Flash uses 5 : 1 with w = 128: 39 window and 9 global layers, because its first layer is global and the first block has only four window layers (config hybrid_layer_pattern).
  • StepFun's Step 3.5 Flash uses 3 : 1 with w = 512, choosing windows over linear attention to maximize decoding efficiency, and puts a sigmoid gate on each head's output.

Small windows expose a quirk of softmax: weights must sum to one, so a head with nothing to read still puts attention somewhere. StreamingLLM found models park it on the first tokens, which every later token sees, and called them attention sinks. Window attention collapses once they leave the window; keeping 4 initial tokens fixes it. gpt-oss instead gives each head a learned bias in the softmax denominator, "which enables the attention mechanism to pay no attention to any tokens". MiMo-V2-Flash copies this on its window layers (config add_swa_attention_sink_bias):

pts = exp(zts) / ( exp(sink) + ∑s′ exp(zts′) ),    zts = query–key logit, sink ∈ ℝ learned per head

In MiMo's 32B ablation a w = 128 hybrid scored 54.9 on MMLU without sinks, 58.3 with them, and all-global attention 57.3.

Figure 3.2 compares which keys each query reads under each scheme.

Attention masks on 12 tokens: full causal, sliding window with w = 4, sparse top-k with m = 4, and compressed blocks of 4 plus a windowFull causalevery earlier tokenkey position s →query position t →work per token grows with tSliding window, w = 4only the last w tokenskey position s →query position t →work per token is at most wSparse top-k, m = 4indexer picks m tokens per querykey position s →query position t →reads m keys; indexer scans all tCompressed + window1 entry per 4 tokens + last 4key position s →query position t →reads t/4 entries + w tokensread by attentionscored by the indexer, not readone compressed entry (4 tokens)not read (masked or future)
Figure 3.2. Which keys each query reads, for 12 tokens (row t = query, column s = key). Sparse top-k reads a few chosen tokens, but its indexer still scores every earlier one. Last panel: V4-style compression, one entry per finished block of 4 tokens, plus the latest tokens read exactly.

Read only what matters: sparse attention

A window chooses what to read by position; sparse attention chooses by content. It keeps the whole cache but reads only a few entries per new token. DeepSeek Sparse Attention (DSA), introduced in DeepSeek-V3.2-Exp and kept in V3.2, adds a lightning indexer that scores each earlier token s for the current token t with HI small heads:

It,s = ∑j=1…HI wt,j · ReLU(qIt,j · kIs)

Main attention then reads only the m = 2048 highest-scoring entries, so its work per token falls from O(n) to O(m). The indexer still scans all n, but it "has a small number of heads and can be implemented in FP8". DSA uses MLA's MQA mode, so each selected latent serves every head. At 128K that is one cached latent in 64.

One DSA decode step in code
def dsa_decode_step(x_t, latents, idx_keys, m=2048):
    # latents:  [t, d_c + d_r]  MLA cache, shared by all heads
    # idx_keys: [t, d_I]        one small indexer key per past token
    q_I, w_I = indexer_queries(x_t)          # [H_I, d_I], [H_I]
    scores = relu(q_I @ idx_keys.T)          # [H_I, t]  few heads, FP8
    I = (w_I[:, None] * scores).sum(axis=0)  # [t] one score per past token
    sel = top_k(I, min(m, len(I)))           # indices of m tokens
    return mla_attention(x_t, latents[sel])  # core attention reads m entries

DSA was added to dense-attention checkpoints by continued training, in two stages from DeepSeek-V3.1-Terminus:

  1. Train only the indexer, on 2.1B tokens: its scores, softmaxed over past tokens, were pulled by a KL loss toward the main attention weights summed over heads and renormalized, so it learns which tokens real attention reads.
  2. Switch on selection and train everything on 943.7B tokens at 128K.

GLM-5 added DSA the same way and reports 1.5–2× less attention compute on long sequences. GLM-5.2 trims the indexer: IndexShare picks top-k once per 4 layers, for 2.9× fewer per-token FLOPs at 1M.

Three more labs select blocks of tokens instead of single tokens, on GQA instead of MLA:

Store fewer entries: compressed attention

DeepSeek-V4 merges consecutive tokens into single cache entries, with two layer types:

  • CSA (Compressed Sparse Attention) layers merge every 4 tokens' KV entries into one entry, a weighted sum whose softmax weights are computed from the tokens, and DSA then picks the top 1024 entries (V4-Pro).
  • HCA (Heavily Compressed Attention) layers merge every 128 tokens into one entry and read all of them.
  • After the first two layers (HCA in V4-Pro, pure sliding window in V4-Flash), the two types alternate by layer. Every layer also attends to the last 128 uncompressed tokens and has sinks.

At 128K tokens a V4-Pro CSA layer keeps 32,768 entries and reads 1,024, an HCA layer keeps and reads 1,024, and both read the last 128 tokens exactly. Together with FP8 storage for most KV dimensions (which alone nearly halves the cache), they bring the cache to about 2% of a BF16 GQA baseline (8 KV heads of dimension 128) at 1M tokens.

Keep a fixed-size memory: linear attention

Linear attention removes the growing cache. Each head keeps one fixed-size matrix, its state S, which every new token updates with its key and value and reads with its query, so memory and work per token are fixed, whatever n is. In the toy, a 128 × 128 state per head is 32 KiB in bfloat16: 1 MiB for a 32-head layer at any length, against 512 MiB at 128K for a GQA layer with 8 KV heads.

The state comes from regrouping attention. Katharopoulos et al. replaced the softmax similarity exp(q·k) with a plain product φ(q)·φ(k). Take φ as the identity and drop the normalizer, as is now common. Because matrix products are associative, the output can be regrouped:

ot = ∑s≤t vs(ks⊤qt) = (∑s≤t vsks⊤) qt = Stqt,    St = St−1 + vtkt⊤ ∈ ℝdv×dk per head

Attention becomes a recurrent network whose state S replaces the cache.

The catch is recall. Reading with a stored key ks returns Stks = ∑s′ vs′(ks′·ks), which equals vs only if ks has unit length and every other key is orthogonal to it. dk-dimensional keys allow that for at most dk tokens, and S can add associations but never remove them, so stored values blur. The DeltaNet paper calls these key "collisions".

Two changes to the write sharpen recall:

  • The delta rule (DeltaNet) first reads what memory returns for kt and moves it toward vt: St = St−1 + βt(vt − St−1kt)kt⊤, one gradient step on ½‖Skt − vt‖².
  • Gating first multiplies S by a learned decay αt ∈ (0, 1).

Gated DeltaNet uses both, since "gating enables rapid memory erasure while the delta rule facilitates targeted updates". Kimi Delta Attention (KDA), from Kimi Linear, gives each key channel its own decay. Figure 3.3 shows one step.

KV cache growth versus the fixed-size gated delta rule state updateSoftmax attentionKV cache: one entry per token⋮+1 entry for every new token;memory grows with nLinear attention: fixed state S (dv​ × dk​ per head)gated delta rule, one token at a timeSt−1​1 forgetS ← α·Sα: scalar (Gated DeltaNet)or per key channel (KDA)2 eraseS ← S − β(Sk)kᵀremove what S returnsfor key k (delta rule)3 writeS ← S + β v kᵀstore the new value;plain linear attention: only thisSt​ot​ = St​ qt​inputs from token t: qt​, kt​ (L2-normalized), vt​,and learned gates αt​ ∈ (0,1), βt​ ∈ (0,1)memory and work per token stay fixed as n grows
Figure 3.3. One gated delta step. Plain linear attention does only step 3; DeltaNet adds step 2; Gated DeltaNet adds step 1 with scalar αt; KDA uses one α per key channel.
One gated delta step in code
def gated_delta_step(S, q, k, v, alpha, beta):
    # S: [d_v, d_k] state; q, k: [d_k] (k L2-normalized); v: [d_v]
    # alpha: scalar (Gated DeltaNet) or [d_k] vector (KDA); beta in (0, 1)
    S = S * alpha                         # 1 forget (per column for KDA)
    v_old = S @ k                         # what memory returns for key k
    S = S + beta * outer(v - v_old, k)    # 2+3 erase old value, write new
    o = S @ q                             # read with the query
    return S, o

A fixed state cannot hold every detail of a long document, so production models keep some full-attention layers, in a ratio written linear : full. A 3 : 1 hybrid of the toy keeps 4 GiB at 128K in its 8 full layers plus 24 MiB of state in the other 24.

Kimi Linear repeats 3 KDA layers and 1 MLA layer (3 : 1); in its ablation 3 : 1 had the lowest validation perplexity, 5.65, ahead of 1 : 1 (5.66, but slower), 7 : 1 (5.70), all-MLA (5.77) and 15 : 1 (5.82). With the same 1.4T-token recipe as a full-MLA baseline, it scored 51.0 vs 47.2 on MMLU-Pro and 84.3 vs 81.3 on RULER at 128K, with up to 75% less KV cache and up to 6× decoding throughput at 1M (per-token time 6.3× faster in its Figure 1).

Other models mix differently:

MiniMax later went the other way. M2 (Oct 2025) returned to full attention in all 62 layers, because hybrids that had matched full attention on standard benchmarks showed deficits in multi-hop reasoning at larger scale.

Side by side

DesignCache per token, per layerAttention work per new token, per layerGives up
MHA2hdh∝ n·h·2dhNothing; largest cache
GQA / MQA2hkvdhSame; h/hkv× less to readSome quality as hkv falls
MLA (absorbed)dc + dr∝ n·h·(2dc + dr)More arithmetic; decoupled RoPE
Window + globalWindow layers: last w tokens only∝ w (window), ∝ n (global)Old tokens in window layers
Sparse top-k (DSA)As MLA, plus an indexer key∝ m, plus a cheap ∝ n indexerMemory unchanged; may miss tokens
Compressed (CSA / HCA)One entry per 4 or 128 tokens, plus last w∝ m + w (CSA), ∝ n/128 + w (HCA)Detail inside each block
Linear (KDA)None: fixed dv×dk state per head∝ dvdkExact recall

Work counts multiply-adds per cached entry and head. MHA needs dh for the score and dh to mix values; absorbed MLA needs dc + dr for the score (latent plus rotary key) and dc to mix latents.

Who uses it and why

"Given that sparsity 48 already offers strong performance, the marginal gains from doubling attention heads do not justify the inference cost."

"we empirically observed that learnable attention sinks bias dramatically enhance the performance of hybrid SWA models, matching or even surpassing baselines with fully GA layers."

"Long-context retrieval remains the primary bottleneck for pure linear attention, we therefore hybridize KDA with a small number of full global-attention (Full MLA) layers"

"The price paid became obvious at a larger scale: the model had clear deficits in complex, multi-hop reasoning tasks."

Trade-offs

  • MLA swaps memory for arithmetic, so head count drives long-context cost.
  • Small windows need sinks, and bigger is not always better: MiMo's 512-token window did worse than 128 on long-context tests.
  • DSA keeps the full cache, its indexer still scans every token, and it must be trained in (943.7B tokens for V3.2).
  • Linear hybrids keep one full layer per three to seven linear ones (3 : 1 at Kimi and Qwen, 7 : 1 at MiniMax-Text-01 and Ling 2.5), and mixed layer types need separate cache layouts in serving.
  • Converting a trained model to windows can fail. MiniMax tried turning M2 into sliding-window hybrids by continued pretraining, and after SFT they did significantly worse than full attention beyond 32K tokens; MiniMax's explanation is that retrieval and induction heads form early in pretraining.

Takeaways

  • Cache per token = numbers stored per layer × layers × bytes. GQA and MLA shrink what a layer stores, windows and compression shrink how many tokens it keeps, and sparse attention shrinks how many it reads.
  • Most 2026 designs are hybrids: a few layers that reach every token, with cheaper window or linear layers between them.
  • Efficient attention can be retrofitted: DSA was added to dense-attention checkpoints by continued training, GQA can be uptrained from MHA, and Ant turned Ling 2.0's GQA layers into Lightning and MLA layers. It does not always work: MiniMax's sliding-window conversions of M2 fell short at long context.
Check yourself: why can't MLA apply RoPE to the keys it expands from the latent?

The rotation in q⊤Rs−tWUKcs depends on each cached token's position, so WUK could not be absorbed and every key would be re-expanded at every step. Decoupled RoPE moves position into a separate small key (64 dimensions in DeepSeek-V3).

Check yourself: DSA reads only 2,048 entries per token. Why doesn't its KV cache shrink, and what in DeepSeek-V4 shrinks it?

Any past token may be selected later, so all n latents stay in memory. V4's CSA and HCA store one compressed entry per 4 or 128 tokens, plus a short window of exact entries.

  1. Vaswani et al., Attention Is All You Need (2017)
  2. Shazeer, Fast Transformer Decoding: One Write-Head is All You Need (MQA, 2019)
  3. Ainslie et al., GQA (2023)
  4. DeepSeek-AI, DeepSeek-V2 (MLA, decoupled RoPE, 2024)
  5. DeepSeek-AI, DeepSeek-V3 Technical Report and config.json
  6. Kimi Team, Kimi K2 Technical Report
  7. Z.ai, GLM-4.5 config.json
  8. Gemma Team, Gemma 3 Technical Report
  9. OpenAI, gpt-oss-120b & gpt-oss-20b Model Card
  10. Xiaomi, MiMo-V2-Flash Technical Report and config.json
  11. Xiao et al., Efficient Streaming Language Models with Attention Sinks (2023)
  12. Yuan et al., Native Sparse Attention (2025), background for compressed and selected sparse branches
  13. DeepSeek-AI, DeepSeek-V3.2-Exp and DeepSeek-V3.2 reports
  14. DeepSeek-AI, DeepSeek-V4 Technical Report
  15. Z.ai, GLM-5 Technical Report and GLM-5.2 blog (IndexShare)
  16. Katharopoulos et al., Transformers are RNNs (2020)
  17. Yang et al., Parallelizing Linear Transformers with the Delta Rule (DeltaNet, 2024)
  18. Yang, Kautz and Hatamizadeh, Gated Delta Networks (2024)
  19. Kimi Team, Kimi Linear Technical Report
  20. Kimi Team, Kimi K3 Technical Report
  21. Z.ai, GLM-5.3-Flash config.json
  22. MiniMax, MiniMax-01 report (2025), MiniMax-M2 series report (2026), Why Did M2 End Up as a Full Attention Model?, MiniMax-M3 and M3.1-Flash model cards
  23. Qwen, Qwen3-Next blog, Qwen3.8 model card and Qwen3.8-Next architecture report (2026)
  24. StepFun, Step-3 report (2025), Step 3.5 Flash report (2026) and Inside Step 5 Preview
  25. Ant, Ling and Ring 2.6 report (2026) and Ling-3.0-flash card; NVIDIA, Nemotron 3 Nano card; Mistral, Large 3 and Small 4 params.json

Lab Memory and compute calculator

How much memory does each attention design need for a long conversation, and how much does it read per generated token?

Pick models and a context length. The calculator uses each model's published configuration (hover a model name for its source) and the formulas from chapters 00 and 03. KV cache is what the model must keep in memory per sequence; reads per token is how many bytes of cache or state one generated token has to read. Numbers assume the cache is stored at the precision stated for the model, or 2 bytes (BF16) when none is stated; linear-attention states are also counted at 2 bytes, and at FP32 they would double.

ModelAttention layersCache per token (average)KV cache per sequence× batchCache read per generated token
KV cache per sequence versus context length
KV cache per sequence (GB, log scale) as context grows from 1K to 1M tokens, for the selected models. The marker shows the chosen context length.

Simplifications: parameters, activations and the optimizer state are not counted; sparse attention still stores every token but reads only the selected ones plus its index; linear-attention layers keep a fixed-size state. See each model's hover note for what is stated and what is assumed.

04 Position information

How does attention know where each token sits, and why do several 2026 models leave position encoding out of their global layers?

Why attention needs position

An attention score depends only on the contents of a query and a key. Shuffle the earlier tokens and each query returns the same weighted sum, so "dog bites man" and "man bites dog" look alike. As the Transformer paper put it, "Since our model contains no recurrence and no convolution, in order for the model to make use of the order of the sequence, we must inject some information about the relative or absolute position of the tokens in the sequence." It added sinusoidal vectors to the input embeddings. Current models put position inside attention instead.

RoPE: rotate queries and keys

Draw two numbers of a query as an arrow in the plane. Rotary position embedding (RoPE), from RoFormer, turns that arrow by tθ for a token at position t, and turns a key at position s by sθ. A dot product is the two lengths times the cosine of the angle between the arrows. Turning changes no lengths, so the score changes only through that angle, which shifts by (s − t)θ: the distance between the tokens, not where they sit.

A toy with easy angles: θ = 20° per position, and a query and key that start 10° apart.

  • Query at 2, key at 4. The query turns 40° and the key 80°, so they end 10° + 40° = 50° apart.
  • Both shifted by 3, to 5 and 7. The query turns 100° and the key 140°: again 50° apart, same score.

Figure 4.1 draws both cases; its right panel shows that a real head turns many pairs, each at its own speed.

RoPE rotates a query and key pair by position-dependent angles; shifting both positions keeps the angle between themquery at t = 2, key at s = 4one pair; θ = 20° per position; φ = 10° at startqkR2​ qR4​ k50°angle = φ + (s − t)·θ = 10° + 2·20° = 50°shift both by 3: t = 5, s = 7one pair; θ = 20° per position; φ = 10° at startqkR5​ qR7​ k50°angle = φ + (s − t)·θ = 10° + 2·20° = 50°Pairs turn at different speedsdh​ = 8, base 10,000, position t = 10i = 0θ = 1213.0°λ = 6.3i = 1θ = 0.157.3°λ = 62.8i = 2θ = 0.015.7°λ = 628i = 3θ = 0.0010.6°λ = 6,283hand: angle t·θi​ (mod 360°)λi​ = 2π/θi​ tokens per full turn
Figure 4.1. Left and middle: q and k start φ = 10° apart (dashed); shifting both positions by 3 turns both vectors by the same extra angle, so their angle and dot product are unchanged. Right: after 10 tokens, the four pairs of an 8-dimensional head have turned by very different amounts.

A head of dimension dh splits each query and key into dh/2 pairs and turns pair i by tθi, with

θi = base−2i/dh,   i = 0 … dh/2 − 1

RoFormer uses base = 10,000, so pair 0 turns one radian per token and later pairs ever more slowly. Call the whole block-diagonal rotation Rt. Rotations add their angles and Rt⊤ = R−t, so, as in the toy, a query at t and a key at s score

(Rtq)⊤(Rsk) = q⊤Rs−tk

Each vector carries its absolute position, but attention sees only the offset s − t. Values are not rotated.

YaRN calls λi = 2π/θi the wavelength: the number of tokens pair i needs for one full turn. In Figure 4.1's right panel, after 10 tokens pair 0 has turned 213° and pair 3 under 1°. Fast pairs separate neighboring tokens; slow pairs barely move over thousands of tokens. The base sets the slowest wavelength, which is why it is tied to context length.

RoPE written out, and in code
(x2i, x2i+1) ↦ (x2i cos tθi − x2i+1 sin tθi,  x2i sin tθi + x2i+1 cos tθi)
def rope(x, pos, base=10_000.0, p=1.0):
    # x: [n, d_h] queries or keys of one head; pos: [n] positions t
    d_h = x.shape[-1]
    i = arange(d_h // 2)
    theta = base ** (-2 * i / d_h)            # [d_h/2], fastest pair first
    theta = where(i < int(p * d_h // 2), theta, 0.0)  # p-RoPE: drop slow pairs
    ang = pos[:, None] * theta[None, :]       # [n, d_h/2] angle t * theta_i
    x1, x2 = x[:, 0::2], x[:, 1::2]           # the d_h/2 pairs
    out = empty_like(x)
    out[:, 0::2] = x1 * cos(ang) - x2 * sin(ang)
    out[:, 1::2] = x1 * sin(ang) + x2 * cos(ang)
    return out                                # p = 1: RoPE; p = 0: no encoding

Worked example: what raising the base does

Take a toy head with dh = 8, so i = 0…3 and θi = base−i/4. The table gives each pair's speed θi and wavelength λi in tokens.

PairSpeed, base 10,000WavelengthSpeed, base 1,000,000Wavelength
016.316.3
10.162.80.0316198.7
20.016280.0016,283
30.0016,2833.16 × 10−5198,692

With base 10,000 the slowest pair turns 32,768 / 6,283 ≈ 5.2 times across a 32K context, so two tokens about 6,283 apart get the same angle on that pair. With base 1,000,000 it turns about 0.16 times. For a head that rotates all 128 dimensions, the longest wavelength is 2π · base126/128: about 54,000 tokens at base 10,000 and about 5.1 million at 1,000,000. Labs raise the base as context grows:

Rotating only part of each head

Many models rotate only some dimensions of each query and key. The rotated ones carry position; the unrotated ones score the same at any distance, so they compare content alone.

Why want such channels? Barbero et al. examined Gemma 7B and found it builds positional patterns from the fastest pairs and gives the slowest pairs the largest query and key norms, apparently using them as channels that compare content. Even slow pairs drift over long distances, so those channels are not robust. Their p-RoPE keeps the fraction p of pairs with the highest frequencies and stops rotating the rest: p = 0 is no encoding and p = 1 is RoPE. In Figure 4.1's toy head, 0.75-RoPE would freeze pair 3. Training 2B models at 8K, 0.75-RoPE reached validation perplexity 4.4414 on Wiki, against 4.4627 for RoPE and 4.8594 with no encoding.

Among the models here:

  • Forced by MLA. In MLA (chapter 03), DeepSeek-V3's keys have 128 unrotated dimensions from the latent plus a 64-dimension rotated key.
  • Chosen. GLM-4.5 sets partial_rotary_factor = 0.5; MiMo-V2-Flash rotates the first 64 of 192 query/key dimensions; DeepSeek-V4 rotates the last 64. Its cached entries serve as both keys and values, so the attention output would carry absolute position; V4 rotates the output back by the query's position, so that it "will also carry relative position embeddings".
  • p-RoPE. Gemma 4 uses p = 0.25 on its global layers and RoPE on local ones, with bases of 1M and 10k.

No position encoding

A decoder can learn position with no encoding at all (NoPE). The causal mask gives each token a different set of visible tokens, and Kazemnejad et al. prove that the first layer can then recover absolute positions: a head that spreads attention evenly and reads a flag set only on the first token outputs 1/t at position t (at position 4 it averages four tokens, one flagged, and outputs 1/4). In their length-generalization tests, NoPE beat RoPE, ALiBi and absolute embeddings.

Several labs now drop RoPE on global layers and get order elsewhere (Figure 4.2):

  • Local RoPE layers. Llama 4's iRoPE interleaves layers "without positional embeddings" among RoPE layers; in Meta's reference code the NoPE layers attend globally, the RoPE layers within local chunks, and at inference NoPE-layer queries are scaled up by a factor that grows with the log of position (beyond 8,192 tokens) to sharpen attention at long range. MAI-Thinking-1 uses RoPE (base 10,000) on its 512-token window layers and nothing on global ones.
  • Linear-attention layers. Kimi Linear and Kimi K3 use NoPE in every MLA layer and let KDA's gated decay carry order and recency; GLM-5.3-Flash's config also turns RoPE off in its MLA layers (mla_use_nope).
  • Mamba layers. NVIDIA's Mamba-2 hybrids, from Nemotron-H on, use no position encoding in any layer, because the Mamba layers provide implicit positional information.

The results cut both ways. In Kimi Linear's matched runs, NoPE beat a RoPE variant on long-context benchmarks, 54.5 vs 51.8 on average (RULER 84.3 vs 78.8), and without a rotary key, MLA also runs as pure MQA at inference. Qwen, however, tested NoPE for Qwen3.8-Flash-Next and kept partial RoPE: the two looked alike in pretraining, but the NoPE variant fell into endless generation far more often after post-training.

Which layers carry RoPE, p-RoPE or no position encoding in five modelsGemma 3local : global = 5 : 1local · RoPE 10klocal · RoPE 10klocal · RoPE 10klocal · RoPE 10klocal · RoPE 10kglobal · RoPE 1Mlocal · RoPE 10klocal · RoPE 10klocal · RoPE 10klocal · RoPE 10klocal · RoPE 10kglobal · RoPE 1MGemma 4local : global = 5 : 1local · RoPE 10klocal · RoPE 10klocal · RoPE 10klocal · RoPE 10klocal · RoPE 10kglobal · p-RoPE 1Mlocal · RoPE 10klocal · RoPE 10klocal · RoPE 10klocal · RoPE 10klocal · RoPE 10kglobal · p-RoPE 1MMAI-Thinking-1local : global = 5 : 1local · RoPE 10klocal · RoPE 10klocal · RoPE 10klocal · RoPE 10klocal · RoPE 10kglobal · NoPElocal · RoPE 10klocal · RoPE 10klocal · RoPE 10klocal · RoPE 10klocal · RoPE 10kglobal · NoPEKimi K3linear : full = 3 : 1KDAKDAKDAMLA · NoPEKDAKDAKDAMLA · NoPEKDAKDAKDAMLA · NoPEGLM-5.3-Flashlinear : full = 3 : 1KDAKDAKDADSA · NoPEKDAKDAKDADSA · NoPEKDAKDAKDADSA · NoPElayer 1 at the bottom; 12 consecutive layers of each repeating patternRoPEp-RoPE (p = 0.25)no position encodingKDA: position from gated recurrence
Figure 4.2. Which layers carry position, over 12 consecutive layers. MAI-Thinking-1 says it follows Gemma 3's periodic design, so its order is drawn the same way. Kimi K3 and GLM-5.3-Flash put 3 KDA layers before each global layer.

Learned relative positions: Inkling

Inkling takes a third route: instead of RoPE it learns a relative position embedding, citing Shaw et al. and the Music Transformer. It works like a table indexed by distance. In Shaw's form, each offset s − t, clipped to [−c, c], has its own learned vector aKts, added to the key inside the score:

ets = xtWQ(xsWK + aKts)⊤ / √dh,    aKts = wKclip(s−t, c)

With c = 2 the table holds five vectors, and keys more than two tokens away share the edge one. Clipping also "enables the model to generalize to sequence lengths not seen during training". Hugging Face's write-up of Inkling describes a fourth projection, besides query, key and value, that produces "a per-token, per-head relative feature R", adjusted by the query-key distance and added into the attention logits. The exact formula has not been published.

Position and context extension

RoPE models are usually pretrained at shorter lengths and extended later (see the midtraining notes). The trouble is the slow pairs. If training stopped at length L, a pair whose wavelength exceeds L only ever saw part of a turn, and positions beyond L give it angles it never saw; the fast pairs have already turned many times, so every angle is familiar to them. In the base-10,000 toy head, 4,096 training tokens show pair 3 (λ = 6,283) about 0.65 of a turn and pair 0 about 650 turns. Four fixes are in use:

  • Raise the base. A larger base leaves the fastest pair (θ0 = 1) alone and slows the others, the slowest most, so over the longer context the slow pairs sweep roughly the angles they swept before, and neighboring tokens stay as easy to tell apart. YaRN describes this base change as "scaling high frequencies less and low frequencies more". MiMo-V2-Flash, for example, raised its global base 7.8× for an 8× longer context. A training stage at the new length then adapts the model to what changed.
  • Position interpolation. Divide positions by a scale factor κ, squeezing the new range into the trained one: with κ = 4, position 10,000 gets the angles of position 2,500. κ is tuned, not set to the length ratio: Gemma 3 found κ = 8 to "work well" for a 4× extension from 32K to 128K.
  • YaRN. Interpolate only pairs whose wavelength is long relative to the training length and leave fast pairs alone. YaRN also divides the logits by a temperature τ, fitted for lowest perplexity (√(1/τ) = 0.1 ln κ + 1), which it ties to attention becoming flatter (higher entropy) at extended lengths. DeepSeek-V3 applied YaRN only to the decoupled key with κ = 40 over a 4,096-token base, which covers 163,840 positions, a margin beyond the 128K it trained at; gpt-oss extended its full layers to 131,072 tokens with κ = 32 from 4,096.
  • No encoding on global layers. NoPE global layers skip this step: Kimi K3 "extrapolates directly to 1M-token contexts without any positional-encoding modification".

Who uses it and why

"The global attention layers do not use any position encoding (Kazemnejad et al., 2023), which performs comparably to RoPE while being more efficient."

"Kimi K3 uses no explicit positional embedding (NoPE), and instead encodes positional information implicitly through the recurrent gating and decay mechanism of KDA."

"We find that encoding position with a relative positional embedding … performs better and extrapolates better to longer sequences than the more widely adopted Rotary Positional Embedding (RoPE)."

Trade-offs

  • RoPE ties the base, and often a rescaling method, to the target context; each extension stage revisits it.
  • Partial RoPE and p-RoPE give up positional resolution in the unrotated dimensions in exchange for content channels that do not drift with distance.
  • NoPE global layers need another source of order (RoPE window layers, KDA's decay, Mamba-2 layers, or the causal mask alone), and the damage may show only after post-training, as in Qwen's test, and Llama 4 adds a log-position query scaling on them at inference.
  • Learned relative embeddings add a term for every query-key pair; Shaw et al. needed a dedicated implementation to keep it efficient.

Takeaways

  • RoPE rotates pairs of query and key dimensions by position, so scores depend only on token offset; the base sets how far the slowest pair reaches.
  • Labs increasingly rotate only part of each head (decoupled, partial or p-RoPE), keeping some dimensions free of position.
  • In hybrids, global layers often carry no position at all, and local or linear layers supply order, which removes base retuning when the context grows.
Check yourself: why does a RoPE score depend only on the offset between two tokens?

The query is rotated by Rt and the key by Rs. Because Rt⊤Rs = Rs−t, the score is q⊤Rs−tk, which is unchanged if both positions shift by the same amount.

Check yourself: with base 10,000 and dh = 128, roughly how long is the slowest pair's wavelength, and what goes wrong at a 128K context?

λ = 2π · 10,000126/128 ≈ 54,000 tokens. If training stopped at 32K, that pair only ever covered about 0.6 of a turn; at 128K it sweeps through angles it never saw. Raising the base, YaRN or NoPE global layers address this.

  1. Vaswani et al., Attention Is All You Need (2017)
  2. Su et al., RoFormer: Enhanced Transformer with Rotary Position Embedding (2021)
  3. Peng et al., YaRN: Efficient Context Window Extension of Large Language Models (2023)
  4. Barbero et al., Round and Round We Go! What makes Rotary Positional Encodings useful? (p-RoPE, 2024)
  5. Kazemnejad et al., The Impact of Positional Encoding on Length Generalization in Transformers (NoPE, 2023)
  6. Shaw et al., Self-Attention with Relative Position Representations (2018)
  7. DeepSeek-AI, DeepSeek-V3 Technical Report and config.json
  8. DeepSeek-AI, DeepSeek-V4 Technical Report
  9. Z.ai, GLM-4.5 Technical Report, GLM-4.5 config.json, GLM-5.2 config.json, GLM-5.3-Flash config.json
  10. Xiaomi, MiMo-V2-Flash Technical Report
  11. Gemma Team, Gemma 3 Technical Report and Gemma 4 Technical Report
  12. Meta, The Llama 4 herd (blog) and reference model.py
  13. Microsoft AI, MAI-Thinking-1 Technical Report
  14. Kimi Team, Kimi Linear Technical Report and Kimi K3 Technical Report
  15. Thinking Machines, Introducing Inkling and Hugging Face write-up
  16. OpenAI, gpt-oss Model Card and config.json
  17. NVIDIA, Nemotron-H report and Nemotron 3 white paper; Qwen, Qwen3.8-Next architecture report

05 The residual stream and normalization

How does a 61-layer model like DeepSeek-V4-Pro keep activations and gradients at a usable size from the first layer to the last, and why did DeepSeek widen that path into four parallel streams?

The residual stream: a running sum

Picture each token carrying one vector of width d up through the network. Each sublayer (attention, then an MLP or MoE, alternating) reads the vector, computes an update and adds it back. Nothing is overwritten, so at the top the vector is the token's embedding plus every update written along the way. This running sum is the residual stream.

xl+1 = xlstream so far + Fl(xl)update,    xl ∈ ℝd for each token   ⟹   xL = xl + ∑i=lL−1 Fi(xi)

A toy with d = 2: the embedding (1, 0), plus attention's update (0, 2), plus the MLP's (1, −1), gives (2, 1). The MLP read (1, 2), which already held attention's write.

Why build it this way? Adding layers should never hurt a network, since the extra layers could learn to copy their input; in practice it did. He et al. called this the degradation problem: deeper plain networks reached higher training error, which rules out overfitting as the cause. Their shortcut lets each block learn only a correction F(x), and adds "neither extra parameter nor computational complexity". The unrolled sum shows why depth becomes trainable: the signal from layer l reaches layer L unchanged, and the gradient ∂xL/∂xl contains an identity term.

The rest of the chapter changes this picture: normalize what sublayers read (pre-norm) and what attention compares (QK-norm), widen the stream into several (HC, mHC, the Gated Residual), or weight earlier writes unequally (AttnRes).

Where the normalization goes

Each read passes through a normalization so the sublayer sees a predictable scale. Most of these models use RMSNorm (Zhang and Sennrich), which divides a vector by its root-mean-square size and multiplies by a learned gain g:

RMSNorm(x) = g ⊙ x / RMS(x),    RMS(x) = √( (1/d) ∑i xi2 ),    x, g ∈ ℝd

For x = (1, 7), RMS = √((1 + 49)/2) = 5, so with g = (1, 1) the output is (0.2, 1.4), the same as for (10, 70). RMSNorm drops LayerNorm's mean subtraction; it matched LayerNorm's quality and cut running time by 7% to 64%. Where the norm sits changes the picture:

  • Post-LN, xl+1 = Norm(xl + F(xl)), as in the original Transformer, normalizes the stream itself after each add. Xiong et al. showed that at initialization this gives large gradients to the parameters near the output, which is why Post-LN needs a learning-rate warm-up.
  • Pre-LN, xl+1 = xl + F(Norm(xl)), normalizes only the copy a sublayer reads and leaves the shortcut untouched. It has well-behaved gradients at initialization and trains without the warm-up. DeepSeek-V3, MiMo-7B and gpt-oss use RMSNorm here.
  • Pre + post, xl+1 = xl + Normout(F(Normin(xl))), also normalizes what the sublayer writes. Gemma 3, Gemma 4 and MAI-Thinking-1 use it.

Pre-LN's cost is that the stream is an unweighted sum whose size keeps growing with depth, which Kimi's Attention Residuals paper says ends up "progressively diluting each layer's relative contribution."

QK-norm: a norm inside attention

Pre-norm bounds the input to attention, but the logit q·k/√dh also grows with Wq and Wk. When Dehghani et al. scaled vision transformers to about 8B parameters, training diverged because logits grew past 50,000 and attention became almost one-hot. QK-norm normalizes each head's queries and keys right before the dot product:

softmax( Norm(XWQ) Norm(XWK)⊤ / √dh ),    X ∈ ℝn×d,   WQ, WK ∈ ℝd×dh per head

The logits then stay in a range set by the learned norm gains: with RMSNorm and gains of 1, query and key each have length √dh, so a logit is at most √dh, about 11.3 for dh = 128. GLM-4.5, Gemma 3, Gemma 4, MAI-Thinking-1 and Muse Spark Open use QK-norm, and Llama 4 Scout applies a weightless version on its RoPE layers (Maverick's config turns it off). Qwen3 added QK-norm to ensure stable training, but in Qwen3-Next Qwen found some of those norm weights growing abnormally large and moved to zero-centered RMSNorm with weight decay on the norm weights. DeepSeek V4 normalizes each query head and its single compressed KV head. QK-norm needs explicit key vectors. In absorbed MLA (Chapter 03) the per-head keys are never formed at inference, so there is nothing to normalize; Chapter 10 shows how Kimi K2, which uses MLA, kept its logits bounded instead.

Hyper-connections: more than one stream

Hyper-connections (HC), from ByteDance, keep nhc copies of the stream (the HC paper's "expansion rate"), a matrix Xl ∈ ℝnhc×d, with three small maps per sublayer:

  • Read. Al ∈ ℝ1×nhc takes a weighted sum of the streams as the sublayer input.
  • Write. Cl ∈ ℝnhc×1 adds the output back to each stream with its own weight.
  • Mix. Bl ∈ ℝnhc×nhc mixes the streams.
Xl+1 = Bl Xlmix + Clwrite Fl(Al Xlread, ∈ ℝ1×d),    Xl ∈ ℝnhc×d,   Fl: ℝd → ℝd

With nhc = 1 and A = B = C = 1 this is the plain residual. F still sees one d-vector, so the sublayers are unchanged, and since nhc is much smaller than d the extra FLOPs are small. In the dynamic version, A, B and C are predicted from the current token. With nhc = 4, OLMoE-1B-7B with HC "converges 1.8 times faster" than without.

The trouble is depth. The signal from sublayer l reaches sublayer L through the product BL−1 ⋯ Bl, and nothing keeps that product near the identity. Small gains compound: sixty mixes that each scale a signal by 1.1 scale it by 1.160 ≈ 304. In DeepSeek's 27B test model, HC's loss surged near step 12k along with the gradient norm, and the worst-case gain of the product (its largest absolute row or column sum) peaked near 3000. A plain residual has gain 1.

mHC: constrain the mixing matrix

DeepSeek's manifold-constrained hyper-connections (mHC) make every mix an average. Each Bl must be doubly stochastic: non-negative, with every row and every column summing to 1, so each output stream is a weighted average of the input streams. With two streams holding 4 and 0, the matrix with rows (0.75, 0.25) and (0.25, 0.75) gives 3 and 1: the total stays 4, and repeated mixing moves the streams toward 2 and 2 without ever growing them. The set of such matrices is called the Birkhoff polytope:

Bl ∈ ℳ = { M ∈ ℝnhc×nhc : M1 = 1,  1⊤M = 1⊤,  M ≥ 0 }    (1: the all-ones vector)

Such a matrix has spectral norm (largest singular value) at most 1, so mixing cannot amplify a signal in the forward or backward pass. Products of doubly stochastic matrices are doubly stochastic, so the bound holds at any depth. For nhc = 1 the only such matrix is 1, the ordinary residual.

Why a doubly stochastic matrix cannot amplify
‖Bl‖2 ≤ √(‖Bl‖1 ‖Bl‖∞) = √(1 · 1) = 1

The spectral norm is at most the geometric mean of the largest column sum ‖B‖1 and the largest row sum ‖B‖∞, both 1 here. Equivalently, a doubly stochastic matrix is an average of permutation matrices (Birkhoff–von Neumann), each with spectral norm 1.

To put each predicted B on this set, mHC exponentiates it so every entry is positive, then runs the Sinkhorn–Knopp algorithm, dividing columns and then rows by their sums, for 20 iterations. A = σ(·) and C = 2σ(·) are kept positive so streams cannot cancel each other. C ranges over (0, 2), so a write weight of 1, the value a plain residual uses, sits in the middle. Twenty iterations give an approximate projection: each layer's own gain stays close to 1, and the gain of the product across all layers of the 27B model peaked at about 1.6 instead of 3000. It finished with 0.021 lower loss than the residual baseline, and BBH rose from 43.8 to 51.0. Figure 5.1 sets the two pictures side by side.

Standard residual versus a four-stream manifold-constrained hyper-connection (a) Standard pre-norm residual xl+1 xl ∈ ℝd RMSNorm F attention or MoE identity shortcut x(l+1) = x(l) + F(RMSNorm(x(l))) (b) Hyper-connections, nhc = 4 streams (mHC) Xl+1 Xl ∈ ℝ4×d A = σ(·): read one d-vector RMSNorm F attention or MoE C = 2σ(·): write back to 4 streams .67 .09 .03 .22 .26 .48 .26 .00 .03 .24 .00 .73 .03 .20 .69 .09 B (4×4) Sinkhorn output: each row and column sums to 1 row = output stream X(l+1) = B·X(l) + C·F(RMSNorm(A·X(l)))
Figure 5.1. (a) A pre-norm residual keeps one d-vector per token. (b) mHC keeps four: A reads a weighted sum into the sublayer, C writes the output back to every stream, and B mixes the streams. The B entries are the learned layer-1 matrix of the mHC paper's 27B model (Xie et al., Fig. 8, p.14), rounded; shaded cells are ≥ 0.40 and grey cells 0.10 to 0.39. Rows sum to 1 and columns to 0.98 to 1.04, since Sinkhorn stops after 20 iterations.
One mHC sublayer in code
def mhc_sublayer(X, F, norm, phi, b, alpha, n_hc=4, t_max=20):
    # X: [n_hc, d] streams of one token
    # phi: [n_hc*d, n_hc**2 + 2*n_hc]; b: [n_hc**2 + 2*n_hc]
    x = X.reshape(-1)                                # [n_hc*d]
    h = (x / rms(x)) @ phi                           # [n_hc**2 + 2*n_hc]
    rd, wr = slice(0, n_hc), slice(n_hc, 2 * n_hc)   # read / write coefficient slots
    A = sigmoid(alpha[0] * h[rd] + b[rd])            # [n_hc] read weights
    C = 2 * sigmoid(alpha[1] * h[wr] + b[wr])        # [n_hc] write weights in (0, 2)
    M = exp(alpha[2] * h[2*n_hc:] + b[2*n_hc:]).reshape(n_hc, n_hc)
    for _ in range(t_max):                           # Sinkhorn-Knopp
        M = M / M.sum(axis=0, keepdims=True)         # columns sum to 1
        M = M / M.sum(axis=1, keepdims=True)         # rows sum to 1
    y = F(norm(A @ X))                               # [d]  one sublayer call
    return M @ X + C[:, None] * y[None, :]           # [n_hc, d]

The gating scalars α start at small values, so the input-dependent part of each map starts small.

DeepSeek-V4-Flash and V4-Pro use nhc = 4 and 20 Sinkhorn iterations. DeepSeek-V4.1-Flash's "Single-Pass mHC" has each block use the read weights predicted by the previous block, so a fused deployment kernel reads and writes the residual once. Z.ai's GLM-5.3-Flash also uses mHC, with hc_mult = 4 and 20 Sinkhorn iterations in its config.

Worked example: what four streams cost in DeepSeek-V4-Pro

V4-Pro has d = 7,168, 61 layers, nhc = 4 and 1.6T parameters.

Per tokenPlain residualmHC, nhc = 4
Residual state, elementsd = 7,168nhc·d = 4 × 7,168 = 28,672
Residual state in BF16 (b = 2)14,336 bytes57,344 bytes
Elements read and written per token per sublayer to maintain the stream, unfused3d = 21,50434d + 48 = 243,760 (mHC Table 2: (8nhc+2)d + 2nhc² + 4nhc)

The plain residual's 3d is: read x, read F's output, write the sum. In pipeline parallelism, consecutive layers live on different GPUs and pass the residual state between them, so a 4× wider state means 4× more traffic between those GPUs (each group is a pipeline stage). Unfused memory traffic grows 243,760 / 21,504 ≈ 11.3×, so DeepSeek fused the mHC kernels, recomputes most hidden states between layers in the backward pass, and reworked its pipeline schedule, which brought the wall-time overhead to 6.7% of a pipeline stage.

Parameters are almost free. The projection that predicts A, B and C is nhc·d × (nhc² + 2nhc) = 28,672 × 24 = 688,128 weights. The V4 inference code has one for the attention sublayer and one for the MoE sublayer in each block, so the 61 blocks hold 61 × 2 × 688,128 = 83,951,616 ≈ 84M weights, about 0.005% of 1.6T.

Reading the stream selectively: AttnRes and the Gated Residual

Kimi attacks the same equally weighted sum from another side. In the plain stream, layer l reads the sum of all earlier outputs, each with weight 1; with Attention Residuals (AttnRes) it learns the weights. Layer l holds one learned vector wl ∈ ℝd, a "pseudo-query", and attends over the earlier layer outputs vi: αi→l = softmaxi(wl⊤ RMSNorm(vi)) and hl = ∑i αi→l vi. The RMSNorm keeps layers with large outputs from dominating the weights.

Keeping every layer's output costs O(L·d) memory per token, so K3 sums the layers inside each block and attends only over block summaries: 8 blocks of up to 12 layers (the last one partial), 9 sources counting the embedding. In Kimi's scaling runs, Block AttnRes matched a baseline trained with 1.25× more compute, at a per-layer memory traffic of 5.5d against 34d for four-stream mHC.

Qwen's Qwen3.8-Flash-Next (Aug 2026) takes a third route. Its Gated Residual also widens the stream to four branches but has no mixing matrix B: each sublayer reads the branches through an elementwise, data-dependent sigmoid gate and writes back with one scalar per branch. Qwen credits the gate as a key contributor to the run's stability (chapter 10).

DesignStreamsA sublayer readsMixing
Pre-norm residual1the normalized sumnone
HC / mHCnhcweighted sum AB: free / doubly stochastic
Block AttnRes1, plus block summariessoftmax over earlier blocksnone
Gated Residual4elementwise sigmoid gatenone

Who uses it and why

"the core idea of mHC is to constrain the residual mapping onto a specific manifold, and thus enhance the stability of signal propagation across layers while preserving model expressivity."

"each layer selectively retrieves representations from all preceding layers rather than accumulating them uniformly."

"We also incorporate QK-Norm [15] to stabilize the range of attention logits."

Trade-offs

  • mHC multiplies the residual state and pipeline traffic by nhc and needs fused kernels, recomputation and schedule changes to stay near 6.7% overhead.
  • Twenty Sinkhorn iterations give an approximate constraint: single-layer gains drift slightly from 1, and the gain composed across all layers reached about 1.6 at worst in the 27B model.
  • Pre-LN trains easily but lets the stream grow with depth; the pre + post form spends an extra norm per sublayer to control it.
  • QK-norm adds a norm per head and needs explicit keys, which MLA's compressed keys do not give at inference.
  • Block AttnRes must keep and send block summaries; K3 checkpoints the AttnRes computation so its saved activations match a standard residual.

Takeaways

  • The residual stream is a running sum that lets signals and gradients skip layers; pre-norm keeps that path clean.
  • Hyper-connections widen the stream to nhc copies with learned mixing, but unconstrained mixing matrices multiply into huge gains across depth.
  • mHC makes each mixing matrix doubly stochastic, so its spectral norm stays at most 1 at every depth; DeepSeek V4 and GLM-5.3-Flash run it with 4 streams.
Check yourself: why does a product of 60 doubly stochastic matrices stay bounded when a product of 60 unconstrained ones does not?

Each doubly stochastic matrix has spectral norm at most 1, and the product is again doubly stochastic, so it also has norm at most 1. Unconstrained matrices with gains slightly above 1 multiply; HC's composite gain reached about 3000 in the 27B model, against about 1.6 for mHC, whose 20 Sinkhorn iterations are only approximate.

Check yourself: for DeepSeek-V4-Flash (d = 4,096, nhc = 4), how many numbers are in each token's residual state, and how many weights are in one mHC projection?

nhc·d = 4 × 4,096 = 16,384 numbers (32,768 bytes in BF16). The projection is nhc·d × (nhc² + 2nhc) = 16,384 × 24 = 393,216 weights.

  1. He, Zhang, Ren, Sun. Deep Residual Learning for Image Recognition (2015).
  2. Xiong et al. On Layer Normalization in the Transformer Architecture (2020).
  3. Zhang and Sennrich. Root Mean Square Layer Normalization (2019).
  4. Dehghani et al. Scaling Vision Transformers to 22 Billion Parameters (2023).
  5. Zhu et al. Hyper-Connections (ICLR 2025).
  6. Xie et al. (DeepSeek-AI). mHC: Manifold-Constrained Hyper-Connections (v2, Jan 2026).
  7. Kimi Team. Attention Residuals (2026).
  8. DeepSeek-AI. DeepSeek-V4 technical report, §2.2, §3.4.2, §4.2.1; V4-Pro inference code (model.py).
  9. DeepSeek-AI. DeepSeek-V4.1 technical report, §2.4.1.
  10. Kimi Team. Kimi K3 technical report, §2.2.
  11. Z.ai. GLM-5.3-Flash blog and config.json; GLM-4.5 report.
  12. Gemma Team. Gemma 3 report; Gemma 4 report. Microsoft AI. MAI-Thinking-1 report. OpenAI. gpt-oss model card.
  13. Qwen. Qwen3 report; Qwen3-Next blog; Qwen3.8-Next architecture report.

06 Multi-token prediction and draft models

How can a model emit several tokens per pass of its large network without changing its output, and why did labs in 2026 start training the network that proposes those tokens separately?

One token per pass

Language models are trained on next-token prediction: at every position t, minimize the cross-entropy of the true next token given all earlier tokens.

L1 = −∑t log Pθ(xt+1 | x1, …, xt)      Pθ(· | x≤t) ∈ ℝV for vocabulary size V

Generation mirrors this: 100 new tokens take 100 forward passes in sequence. Leviathan et al. observed that such inference is often limited by memory bandwidth: each pass reads all the weights and the KV cache to produce one token, and much of the compute sits idle (chapter 00). Two separate ideas put that idle compute to work:

  • MTP as a training signal. Multi-token prediction (MTP) adds a loss for tokens further ahead. Decoding is unchanged, and the extra module can be thrown away.
  • Speculative decoding. A cheap draft model guesses several tokens and the large model checks them all in one pass. Training is unchanged, and the output distribution stays exactly the same.

The two meet when a trained MTP module serves as the drafter.

Multi-token prediction as a training signal

Gloeckle et al. (2024) asked the model to predict the next few tokens at every position, with a shared trunk and one independent output head per future token. As an extra loss this helped at scale: their 13B models solved 12% more HumanEval and 17% more MBPP problems than next-token baselines, while small models got worse.

DeepSeek-V3 made the extra predictions sequential. Take "the cat sat on": at "cat" the main model predicts "sat", and the first MTP module, given the main model's hidden state at "cat" and the embedding of the true "sat", predicts "on". In general, the j-th module takes the hidden state htj−1 at position t (from the main model when j = 1) and the embedding of token xt+j, merges them, and runs one transformer block TRMj to predict token xt+j+1. Embedding and output head are shared with the main model. DeepSeek says this keeps "the complete causal chain at each prediction depth": because module j sees the actual token xt+j, its prediction is conditioned on every earlier token x1 … xt+j, as the main model's is.

h′tj = Mj [ RMSNorm(htj−1) ; RMSNorm(Emb(xt+j)) ]      Mj ∈ ℝd×2d,  h ∈ ℝd
Pjt+j+1 = OutHead( TRMj(h′j)t ) ∈ ℝV      L = Lmain + (λ / Dmtp) ∑j=1…Dmtp LjMTP

Dmtp is the number of extra tokens predicted (DeepSeek calls it the depth). V3 used Dmtp = 1 and loss weight λ = 0.3 for the first 10T tokens, then 0.1 for the last 4.8T. GLM-4.5 and MiMo-7B used the same 0.3 → 0.1 schedule. In V3's ablation on a 228.7B-parameter MoE, the module raised HumanEval from 44.5 to 53.7 at identical inference cost, since the module can be discarded after training.

Speculative decoding: draft, then verify

Speculative decoding pairs the large target model (next-token distribution p) with a cheap draft model (distribution q). One cycle has four steps:

  1. The draft proposes γ tokens one at a time.
  2. The target scores all γ + 1 positions in one pass, as it would a prompt.
  3. Checking left to right, the target accepts each drafted token x with probability min(1, p(x)/q(x)) and stops at the first rejection.
  4. The target samples one token itself: from the leftover distribution norm(max(0, p − q)) at the rejected position, or from its own p at the next position if all γ drafts were kept.

Each cycle yields between 1 and γ + 1 tokens, and the output is distributed exactly as p, however poor the draft. A toy with three words and one drafted token shows why. For each word the table gives q, p, the chance min(1, p/q) of keeping it if drafted, and its leftover max(0, p − q):

WordDraftTargetKept if draftedLeftover
"the"0.60.55/60
"a"0.30.410.1
"an"0.10.110

A drafted "the" is rejected one time in six, 0.6 × 1/6 = 0.1 of all cycles, and every rejection resamples "a", the only word with leftover mass. So "the" comes out 0.6 × 5/6 = 0.5 of the time, "a" 0.3 + 0.1 = 0.4 and "an" 0.1: exactly p. The draft survives 0.9 of the time, the overlap of the two distributions:

β = ∑x min(p(x), q(x))chance the draft is kept = 1 − TV(p, q)    (toy: 0.5 + 0.3 + 0.1 = 0.9)

TV is total-variation distance (the paper calls it DLK); the box gives the general proof.

Why the output is distributed exactly as p
P(output x) = q(x) · min(1, p(x)/q(x)) + (1 − β) · (p(x) − q(x))+ / (1 − β) = min(p, q)(x) + (p − q)+(x) = p(x)

First term: x is drafted and kept. Second: a rejection (probability 1 − β), after which the leftover distribution picks x.

Now chain γ drafts. Let α be the average β and assume acceptances are independent. Draft i is kept only if drafts 1 … i all are, with probability αi, and the target always adds one token, so the expected yield is a geometric sum. For α = 0.9 and γ = 4 it is 1 + 0.9 + 0.81 + 0.729 + 0.656 ≈ 4.1.

E[tokens per target pass] = 1 + α + … + αγ = (1 − αγ+1) / (1 − α)

The expected tokens per target pass is called the acceptance length. Let c be the cost of one draft step relative to one target pass, and assume verifying γ + 1 tokens costs about one ordinary pass, as it does while decoding is memory-bound. A cycle then costs γc + 1 passes:

walltime speedup = (1 − αγ+1) / (1 − α)tokens per cycle ÷ (γc + 1)cost per cycle, in target passes

With c = 0.1 the toy's 4.1 tokens take 1.4 passes, about 2.9× faster. Figure 6.1 draws such cycles to scale.

Draft, verify, accept or reject: a timeline plain 1 token per pass target target target target target target target target target speculative 4 drafts + 1 verify draft verify verify verify 3 tokens 5 tokens 1 token speculative: 9 tokens from 3 target passes plain: 4 tokens in the same time time draft accepted first rejected draft discarded sampled by the target (correction or bonus)
Figure 6.1. To scale for γ = 4 and an assumed draft cost c = 0.1; outcomes are illustrative. Three verify passes emit 3 + 5 + 1 = 9 tokens while plain decoding emits 4.
One speculative cycle in code
def speculative_step(target, draft, prefix, gamma):
    xs, qs = [], []
    for _ in range(gamma):                      # 1. draft gamma tokens
        q = draft.next_dist(prefix + xs)        # [V]
        xs.append(sample(q)); qs.append(q)
    ps = target.dists(prefix, xs)               # 2. one pass: [gamma+1, V]
    for i, x in enumerate(xs):                  # 3. verify left to right
        if uniform() < min(1.0, ps[i][x] / qs[i][x]):
            continue                            # accepted
        resid = maximum(ps[i] - qs[i], 0.0)     # rejected: resample from
        t = sample(resid / resid.sum())         # the leftover mass of p
        return prefix + xs[:i] + [t]
    return prefix + xs + [sample(ps[gamma])]    # 4. all kept: bonus token

MTP modules as drafters

Here the two ideas meet. A trained MTP module is a ready-made draft model: small, fed by the target's hidden state, and trained to predict ahead. DeepSeek-V3's single module reached 85–90% acceptance for the second token and 1.8× tokens per second. MiMo-7B fine-tuned two extra MTP layers after pretraining; the first layer accepted about 90% and the third above 75%.

Drafting several steps from one module creates a mismatch: training feeds each step the target's hidden states, inference feeds later steps the module's own outputs. GLM-5 trained 3 MTP steps with shared weights to close that gap and reported an acceptance length of 2.76 against 2.55 for DeepSeek-V3.2 at 4 speculative steps. GLM-5.2 changed three more things:

  • Shared state. It shared the KV cache and sparse-attention indices across steps.
  • A loss on acceptance. It trained with an end-to-end TV loss; since β = 1 − TV, that loss targets acceptance directly.
  • Rejection sampling. It adopted the min(1, p/q) test above, following Bebop (2026), which contrasts it with a common "target-only" check: the draft proposes its single most likely token ŷ and the target keeps it with probability p(ŷ).

In an ablation on the GLM-5.1 backbone with 7 MTP steps in training and inference, acceptance length on coding rose from 4.56 to 5.47.

2026: drafters trained on their own

During 2026 several labs took the drafter out of backbone pretraining or retrained it afterwards. A separate drafter no longer shapes backbone pretraining, can be retrained whenever the policy changes (which matters for RL, where generating rollouts is the bottleneck), and can draft many tokens per pass while training on acceptance itself.

  • DeepSeek V4.1-Flash dropped the MTP module from backbone pretraining. Its DSpark drafter, three transformer blocks that compute five draft positions in one pass, trains in its own stage with the backbone frozen, then keeps training through post-training (RL and on-policy distillation, OPD) without sending gradients into the backbone. A confidence head predicts which drafts will survive, and a scheduler uses it to pick how many to verify per request.
  • Xiaomi MiMo-V2.6 keeps an MTP objective in pretraining but drafts with a 5-layer DFlash block-diffusion model. Block diffusion here means the drafter takes a block of masked future positions after one known anchor token, lets them attend to each other in both directions, and fills the whole block in one forward pass. MiMo's version predicts 7 tokens in one forward pass. For RL rollouts, a variant with draft block size 6, fine-tuned on rollout logs, gave 31.3% longer accepted lengths than the MTP-3 setup it replaced.
  • Gemma 4's drafters ship as separate "-assistant" checkpoints: 4-layer transformers that cross-attend to the target's KV cache, so they need no prefill. Google reports up to 3× faster decoding.
  • Kimi K3 fine-tunes its pretrained MTP layer into an EAGLE-3 draft model with the target frozen. Training unrolls the draft for seven steps and from the second step on feeds it its own earlier predictions, as happens at inference (EAGLE-3 calls this "training-time test"). It minimizes the LK loss −log ∑x min(p(x), q(x)), the negative log of the acceptance rate.
  • Meta trained Muse Glimmer's DFlash drafter offline on the target's own rollouts; it decodes 3.1× faster on an RTX 5090.

The recipe descends from EAGLE (2024), a one-decoder-layer draft head on the frozen target's features that gave 2.7×–3.5× speedups on LLaMA2-Chat 70B.

Worked example: from acceptance to speedup

DeepSeek-V3, one draft token. With γ = 1 and α = 0.85–0.90, tokens per target pass are (1 − α2)/(1 − α) = 1 + α = 1.85 to 1.90. DeepSeek measured 1.8× tokens per second, so drafting and verification cost only a few percent.

GLM-5.2, seven draft tokens. If acceptances were independent, an acceptance length of 5.47 at γ = 7 means α ≈ 0.888, since (1 − 0.8888)/(1 − 0.888) = 0.613/0.112 ≈ 5.47. The 4.56 baseline means α ≈ 0.830. Under 6 points per token compounds over seven steps into a 20% longer acceptance length.

Draft cost. GLM does not state c; assume c = 0.02. Then speedup ≈ 5.47 / (1 + 7 × 0.02) = 5.47 / 1.14 ≈ 4.8×, against 4.56 / 1.14 ≈ 4.0× for the baseline. With the draft cost unchanged, the 20% gain in acceptance length passes straight into speed.

Who uses it and why

"The training-inference discrepancy reduces the acceptance rate of the second token. Therefore, we propose sharing the parameters of 3 MTP layers during training."

"MTP acceleration is particularly well-suited for RL training (RadixArk Team, 2025), where the rollout phase consistently emerges as the dominant bottleneck"

"This keeps DSpark aligned with the evolving policy, enabling it to accelerate both online serving and rollout generation for RL and OPD."

Trade-offs

  • Every draft step adds cost c, and rejected drafts are wasted work; at low α decoding can get slower.
  • The speedup assumes that verifying γ + 1 tokens costs about one decoding pass. That fails at large batch sizes, so MiMo picks its draft block by end-to-end throughput: a draft block of size 6 beat one of size 8 by about 6%.
  • Acceptance falls when the target drifts from what the drafter learned, so DeepSeek keeps training DSpark through post-training and MiMo fine-tunes DFlash on RL rollouts.
  • MTP as a training loss helped large models but hurt small ones in Gloeckle et al., and Moonshot left it out of Moonlight because it showed no significant benefit.
  • A separate drafter is one more artifact to train and ship per target; Gemma 4 has one per model size.

Takeaways

  • Speculative decoding keeps the target's output distribution exactly; its speed depends on acceptance α, draft length γ and draft cost c.
  • MTP began as an extra training loss (DeepSeek-V3: depth 1, λ 0.3 → 0.1) whose module doubled as a one-token drafter with 85–90% acceptance.
  • In 2026 labs moved to multi-step drafters trained apart from the backbone (DSpark, DFlash, Gemma 4's assistants, Kimi K3's EAGLE-3 draft) that can follow a changing policy and optimize acceptance directly.
Check yourself: a draft model always proposes the word "the". Does speculative decoding with it change what the target generates?

No. Accepting each draft with probability min(1, p/q) and resampling a rejection from norm(max(0, p − q)) produce exactly p, as the toy and the proof above show. The bad draft only drives α toward p("the"), so most cycles yield a single token and the drafting cost makes decoding slower.

Check yourself: with α = 0.8 and free drafting, how many tokens per target pass do γ = 2 and γ = 5 give?

(1 − 0.83)/0.2 = 2.44 and (1 − 0.86)/0.2 ≈ 3.69, matching the 2.44× and 3.69× speeds in Leviathan et al.'s Table 1 for c = 0. Later drafts count only if all earlier ones survive, so returns diminish.

  1. Gloeckle et al. Better & Faster Large Language Models via Multi-token Prediction (2024)
  2. Leviathan, Kalman, Matias. Fast Inference from Transformers via Speculative Decoding (2023)
  3. Li et al. EAGLE: Speculative Sampling Requires Rethinking Feature Uncertainty (2024)
  4. Li et al. EAGLE-3: Scaling up Inference Acceleration of Large Language Models via Training-Time Test (2025)
  5. DeepSeek-AI. DeepSeek-V3 Technical Report (2024)
  6. DeepSeek-AI. DeepSeek-V4.1-Flash Technical Report (2026)
  7. Z.ai. GLM-5 Technical Report (2026) and GLM-5.2 blog
  8. Xiaomi. MiMo-7B report (2025), MiMo-V2-Flash report (2025) and MiMo-V2.6 report (2026)
  9. Gemma Team. Gemma 4 report (2026) and gemma-4-31B-it-assistant model card
  10. Kimi Team. Kimi K3: Open Frontier Intelligence (2026) and Moonlight report (2025)
  11. Meta. Muse Glimmer 30B report (2026) and model card
  12. Qwen, Qwen3.5 blog; MiniMax, MiniMax-M3 model card

07 Multimodal input

How does a language model take in a photo or a sound clip, and why are labs replacing attached vision encoders with raw pixel patches fed straight into the model?

Pixels and sound as vectors

A transformer reads a sequence of vectors of width d; for text they come from an embedding table. The Vision Transformer (ViT) turns an image into such a sequence in three moves:

  1. cut the image into square patches of side p pixels;
  2. flatten each into p²·C numbers (C = 3 colors);
  3. map each to the encoder width dv with one learned matrix Wpatch, and add a learned position vector.

A 28×28 image with p = 14 gives a 2×2 grid of patches of 14 · 14 · 3 = 588 numbers each. In general an H×W image gives P = HW / p² patches, the rows of X:

z0 = XP × p²C, patches · Wpatchp²C × dv, learned + WposP × dv, position

Transformer layers of width dv follow. Vectors like these that enter a language model (LM) are soft tokens (Gemma 3's term), written "at the corresponding image-token positions in the input embedding sequence" (DeepSeek-V4.1-Flash).

Audio is cut along time. Gemma 4 12B slices 16 kHz audio into 40 ms chunks of 16,000 × 0.04 = 640 samples. Other systems encode a log-mel spectrogram, the energy in each frequency band of each short frame. dMel skips the encoder: it rounds each of 80 mel energies to one of 16 levels, a discrete code per frame.

Three routes into the model

Every design ends with soft tokens in the LM's input. The designs differ in what makes those vectors and when the LM first trains on them:

  • Adapter on a frozen encoder. A small projector is trained between a separately pretrained, frozen encoder and a finished text model.
  • Continued pretraining. The encoder is attached to a text checkpoint, and the whole model keeps training on mixed data.
  • Native early fusion. Images are in the mix from the LM's first step, through an encoder or through one light projection that leaves the visual processing to the LM.

Figure 7.1 draws the routes side by side, splitting the native route by whether an encoder remains; the bar under each column marks when image data joins training.

Four ways to feed images to a language model1 · Late adapterimageViT (CLIP ViT-L/14)pretrained, frozenlinear projector Wlanguage modelfrozen in stage 1next-token predictionWHEN IMAGES JOIN TRAININGtext pretrainingillustrativeLLaVA (2023): train W first,then fine-tune W and the LM2 · Continued trainingimage / video / audioViT, pretrainedthen trained with the LMMLP projectorlanguage modeltext checkpoint, continuesnext-token predictionWHEN IMAGES JOIN TRAINING26T text22T omniMiMo-V2.6-Flash, to scaleKimi-VL, Kimi K2.5,MiMo V2.5 / V2.6, GLM-4.5V3 · Native, with encoderimage / videoViT: pretrained apartor from scratch (K3);frozen in Gemma 3*MLP projectorlanguage modeltrained from step 0next-token predictionWHEN IMAGES JOIN TRAINING45T, mixed from step 0DeepSeek-V4.1-FlashGemma 3, Llama 4, Kimi K3,DeepSeek-V4.1-Flash,GLM-5.3-Flash4 · Native, encoder-freeraw patches, audio framesone matmul or hMLP+ 2D position, LayerNormlanguage modeldoes the visual processingnext-token predictionWHEN IMAGES JOIN TRAINING50T, 18% vision-languageMAI-Base-2Gemma 4 12B, Inkling,MAI-Base-2dashed: frozen (not updated)text-only trainingimage, video or audio in the mix
Figure 7.1. Four ways to feed images to an LM. Dashed outlines mark frozen weights; each bar shows when image data joins one run, scaled to that run's length (column 1 is illustrative). *In column 3 the encoder's treatment varies: Gemma 3 keeps it frozen throughout, DeepSeek-V4.1-Flash freezes it until learning-rate decay, and Kimi K3 trains it from the first step.

Adapter: a pretrained encoder plus a projector

Raw pixels through one matrix are a weak start, so early vision-language models borrowed an encoder that had already learned to see. Contrastive training gives matching image-caption pairs similar vectors. SigLIP replaces CLIP's softmax over the whole batch with a sigmoid on each pair, which "does not require a global view of the pairwise similarities for normalization".

LLaVA (2023) set the baseline: a frozen CLIP ViT-L/14 and one trainable matrix W into the LM's word-embedding space. Stage 1 trains only W, "a compatible visual tokenizer for the frozen LLM"; stage 2 also tunes the LM.

Continued pretraining: vision added to a text checkpoint

Next, labs attached the encoder to a text checkpoint and trained the whole model on mixed data for trillions of tokens:

  • Kimi-VL added 2.3T joint tokens to a Moonlight checkpoint trained on 5.2T text tokens.
  • Kimi K2.5 added 15T vision-text tokens to a near-end K2 checkpoint, with a 400M SigLIP-initialized MoonViT-3D.
  • MiMo-V2.6-Flash trained 26T text tokens, then 22T omni-modal tokens with its 681M ViT and audio encoder attached.
  • GLM-4.5V trained an AIMv2-initialized ViT, an MLP adapter and GLM-4.5-Air together for 120,000 steps.

This reuses the costly text model but abruptly shifts its input distribution. With the total vision-text budget fixed, Kimi found that adding vision from 0% of training at a 10:90 ratio beat adding it at 80% with 50:50 on all six vision and text scores (text knowledge 45.5 against 43.1), and that later injection caused a "dip-and-recover" in text ability. K2.5 therefore mixes vision at a constant ratio.

Native multimodal pretraining

Native models see images from the LM's first step. Several labs now train this way:

  • Llama 4's early fusion puts text and vision tokens into one backbone, with a MetaCLIP-based encoder trained separately against a frozen Llama.
  • Gemma 3 mixes images in through its frozen encoder.
  • GLM-5.3-Flash, "the first natively multimodal model in the GLM-5 series", uses a 30T-token multimodal corpus.
  • Qwen3.5 (Feb 2026) brought vision into its flagship base through early text-vision fusion, and MiniMax M3 (Jun 2026) mixed text, image and video from the first step.

DeepSeek-V4.1-Flash prepares its encoder in steps:

  1. pretrain the ViT apart, with SigLIP's loss on about 47B pairs;
  2. continue it with next-token training on 236B tokens through a throwaway 4B MoE LM;
  3. keep it frozen in the main run until learning-rate decay, while that run mixes text-only and multimodal tokens 7:1 over 45T tokens.

The main run also gives each modality its own MoE load-balancing biases, because image and text tokens may prefer different experts.

Kimi K3 trains its 401M MoonViT-V2 from scratch with next-token prediction. In Kimi's ablation, a SigLIP-initialized encoder made joint training unstable: its gradient norms stayed higher and spiked often. Kimi also argues that a contrastive loss favors global meaning over fine text and structure. The from-scratch encoder matched the SigLIP-initialized one on vision evaluations.

Encoder-free: patches straight into the language model

Encoder-free designs keep only a light patch embedding and let the LM's own layers do the perception. Gemma 4 12B maps each 48×48×3 RGB patch (6,912 numbers) through one 35M-parameter matmul in place of a 550M ViT, then adds 2D coordinate embeddings and a LayerNorm. Its 305M audio encoder is gone too: each raw 40 ms chunk is projected directly.

Inkling feeds audio as dMel spectrograms and images as 40×40-pixel patches through a four-layer hMLP. This hierarchical MLP stem (Touvron et al.) merges sub-patches step by step with linear layers and never mixes neighboring patches, like a convolution whose kernel equals its stride. MAI-Base-2 is also encoder-free; vision-language data made up 18% of its 50T-token mix, from 4.5T unique tokens.

Google cites latency, memory use and memory fragmentation, and notes the 12B can be fine-tuned in one pass. Thinking Machines chose it to fit its interaction models, which let users collaborate "using voice and vision in real time".

What an image costs in tokens

Every vector costs the LM one context position, so most designs merge neighboring patches first:

  • Pooling. Gemma 3's frozen 400M SigLIP encoder takes 896×896 inputs and average-pools 4×4 to 256 tokens. Since the encoder never changes, Google pre-computes the embeddings, adding no encoder cost to training.
  • Pixel shuffle. Kimi-VL stacks each 2×2 block of features into one four-times-wider vector before a two-layer MLP.

With patch side p and merge factor r, each LM token covers an rp × rp square of pixels. At p = 14 and r = 2 that is one token per 28² = 784 pixels, so a 448×448 image costs (448/28)² = 16² = 256 tokens. In shapes, for an encoder of width dv and an LM of width d:

F ∈ ℝ(H/p)×(W/p)×dv → ℝ(H/rp)×(W/rp)×r²dv → MLP → ℝ(HW/(rp)²)×d
Image, encoder-free and audio tokens in code
def patchify(img, p):              # img (H, W, C); p divides H, W
    H, W, C = img.shape
    x = img.reshape(H//p, p, W//p, p, C).transpose(0, 2, 1, 3, 4)
    return x.reshape(H//p, W//p, p * p * C)    # flattened patches

def unshuffle(g, r):                # r x r neighbours -> channels
    h, w, c = g.shape
    g = g.reshape(h//r, r, w//r, r, c).transpose(0, 2, 1, 3, 4)
    return g.reshape(h//r, w//r, r * r * c)

def encoder_tokens(img, vit, mlp, p=14, r=3):    # DeepSeek-V4.1
    f = vit(patchify(img, p))                   # (H/p, W/p, 1024)
    return mlp(unshuffle(f, r)).reshape(-1, d)   # (HW/(rp)^2, d)

def encoder_free_tokens(img, W_in, pos, p=48):   # Gemma 4 12B
    x = patchify(img, p) @ W_in                  # 6912 -> d
    return layer_norm(x + pos).reshape(-1, d)

def audio_tokens(wave, W_a, n=640):   # 40 ms of 16 kHz per token
    frames = wave[: len(wave) // n * n].reshape(-1, n)
    return frames @ W_a                          # 25 tokens/s

x = embed(ids)                                   # text rows
x[image_slots] = encoder_tokens(img, vit, mlp)   # soft tokens

Worked example: how many tokens is one image?

DeepSeek-V4.1-Flash at its largest input, about 1344×1344, with patch 14, ViT width 1,024 and 3×3 unshuffle:

  1. 1344 / 14 = 96, so 96² = 9,216 patches of 14 · 14 · 3 = 588 numbers.
  2. Unshuffle: 96 / 3 = 32, so 32² = 1,024 positions of 9 × 1,024 = 9,216 features, the report's "factor of nine".
  3. The MLP maps each to the LM width: 1,024 tokens, one per 42² = 1,764 pixels.
ModelPixels per tokenImageTokens
Gemma 356² (4×4 pool, 14-px patch)896²16² = 256
DeepSeek-V4.1-Flash42² (3×3 merge, 14-px patch)1344²32² = 1,024
Gemma 4 12B48² (no merge)768²16² = 256
Kimi K328² (2×2 merge, 14-px patch)3584²128² = 16,384

Gemma 3's 14-pixel patch is implied: 256 = 16² tokens after 4×4 pooling means a 64-wide grid, and 896 / 64 = 14. Gemma 4 12B's processor caps images at 280 tokens by default. Kimi K3's 1,048,576-token context fits 1,048,576 / 16,384 = 64 maximum-size images. At 40 ms per token, audio costs 25 tokens per second; Gemma 4 12B's default of 750 audio tokens is 30 seconds.

Who uses it and why

"Early fusion with a lower vision ratio yields better results given a fixed total vision-text token budget."

"We depart from this practice primarily for training stability. When a pre-trained encoder is attached to the LLM, joint optimization becomes unstable"

"Because these split encoders add latency and increase memory usage, we trained Gemma 4 12B with an encoder-free architecture to integrate audio and vision input directly."

Trade-offs

  • Frozen encoder: cheap, but it fixes the resolution. Gemma 3's 896×896 input made small text unreadable, so Google added Pan & Scan crops at inference.
  • Continued training: reuses the text model, but text skills can dip when vision arrives. Any joint vision-text training also unbalances the pipeline, since images vary in size. K2.5's Decoupled Encoder Process runs the small encoder first, spread evenly over all GPUs, then the LM, then recomputes the encoder for its backward pass, keeping 90% of text-only efficiency.
  • Native from step 0: multimodal data takes a share of the biggest run (one eighth of 45T, about 5.6T tokens, at DeepSeek; 18% of 50T, 9T, at MAI) and complicates the training system: DeepSeek needs separate routing biases for image and text tokens.
  • Encoder-free: perception runs at the full LM's cost per token, and the LM must learn low-level vision from pretraining data.

Takeaways

  • Patch side p and merge factor r set an image's cost: one token per (rp)² pixels, from 784 in Kimi K3 to 3,136 in Gemma 3.
  • The field moved from late adapters to continued joint training to joint training from step 0; Kimi found early, low-ratio fusion best at a fixed budget.
  • Encoder-free models (Gemma 4 12B, Inkling, MAI-Base-2) replace the encoder with a light patch projection (one matmul or a small hMLP); Google and Thinking Machines cite latency, memory and real-time use.
Check yourself: how many tokens does Kimi K3 spend on a 1792×1792 image?

1792 / 14 = 128 patches per side, so 128² = 16,384 patches. The 2×2 pixel shuffle divides by 4: 4,096 tokens.

Check yourself: why did Kimi K3 drop the SigLIP initialization that K2.5 used?

Joint training with the SigLIP-initialized encoder showed persistently higher gradient norms and frequent spikes. Next-token training shapes the encoder for the LM instead of for global semantics, and the from-scratch encoder matched the SigLIP baseline.

  1. Dosovitskiy et al., An Image is Worth 16x16 Words (ViT), 2020
  2. Zhai et al., Sigmoid Loss for Language Image Pre-Training (SigLIP), 2023
  3. Liu et al., Visual Instruction Tuning (LLaVA), 2023
  4. Touvron et al., Three things everyone should know about Vision Transformers (hMLP stem), 2022
  5. Bai et al., dMel: Speech Tokenization made Simple, 2024
  6. Gemma Team, Gemma 3 Technical Report
  7. Gemma Team, Gemma 4 Technical Report; Gemma 4 12B blog; model card; processor_config.json
  8. Kimi Team, Kimi-VL Technical Report
  9. Kimi Team, Kimi K2.5 Technical Report; model card
  10. Kimi Team, Kimi K3 Technical Report; model card
  11. DeepSeek-AI, DeepSeek-V4.1-Flash Technical Report
  12. Xiaomi MiMo, MiMo-V2.6 Technical Report; MiMo-V2.5 blog
  13. GLM-V Team, GLM-4.1V-Thinking and GLM-4.5V; GLM-5.3-Flash blog
  14. Meta, The Llama 4 herd
  15. Thinking Machines, Introducing Inkling
  16. Microsoft AI, Frontier Pre-training at Microsoft AI (MAI-Base-2)
  17. StepFun. Step 3.5 Flash report. Qwen. Qwen3.8-Next architecture report. NVIDIA. Nemotron 3 Nano report. Ant. Ling 2.0 report. MiniMax. MiniMax-01 report.

08 Optimizers: AdamW and Muon

What does Muon do to a weight matrix's update that AdamW does not, and why did seven of the eleven labs that name their pretraining optimizer move their weight matrices to it by October 2026?

From SGD to Adam: a step size for every weight

Stochastic gradient descent moves each weight by −η times its gradient, where η is the learning rate. Momentum keeps a running sum of past gradients, Mt = μMt−1 + Gt, and steps along that instead, which smooths out batch-to-batch noise. One learning rate η must then suit every weight, whether its gradients are large or small.

Adam (Kingma and Ba) sets the scale per coordinate. For each weight it keeps a running mean of the gradient, m, and of the squared gradient, v, and steps by about η · m/√v. Multiplying every gradient by 1,000 leaves that ratio unchanged; what it measures is how consistent the gradient has been:

  • Steady gradient. A gradient of 0.001 at every step drives m and √v both to 0.001: a step of η. A steady gradient of 10 gives the same step.
  • Noisy gradient. A gradient flipping between +1 and −1 leaves m near ±0.05 (with β1 = 0.9) and √v at 1: a step of about 0.05η.

In full, β1 and β2 set how long each average remembers, and the hats correct both averages for starting at zero:

mt = β1mt−1 + (1−β1)gt    vt = β2vt−1 + (1−β2)gt2    m̂t = mt/(1−β1t)    v̂t = vt/(1−β2t)
θt = θt−1 − η ( m̂t / (√v̂t + ε) + λθt−1 )     (AdamW; all operations elementwise, θ, g, m, v ∈ ℝN)

The paper's defaults are β1 = 0.9 and β2 = 0.999; DeepSeek-V3 and MiMo use a shorter memory for v, β2 = 0.95. Adam stores two extra numbers per parameter.

The λθ term is weight decay: each step also shrinks every weight by the fraction ηλ. Libraries used to implement it as an L2 penalty added to the gradient. Loshchilov and Hutter showed that inside Adam that penalty also gets divided by √v̂, so weights with large past gradients are regularized less. AdamW applies the decay directly to the weights, outside the adaptive scaling, as in the equation above. DeepSeek-V3, MiMo-7B and MAI-Thinking-1 all use λ = 0.1 (MAI lowers it for attention and embedding weights).

Muon: equalize the directions of a matrix update

Adam treats a d×d weight matrix as d² unrelated numbers. Keller Jordan observed that the updates SGD-momentum and Adam produce for transformer weight matrices "typically have very high condition number": they are close to low-rank, dominated by a few directions. Muon (MomentUm Orthogonalized by Newton–Schulz) works on the whole matrix: it keeps SGD momentum and replaces the momentum matrix by the nearest semi-orthogonal matrix (orthonormal rows or columns, so all its singular values equal 1).

A 2×2 example shows what that does:

G = [[3, −0.4], [4, 0.3]]   ⟶   O = [[0.6, −0.8], [0.8, 0.6]]

The columns of G, (3, 4) and (−0.4, 0.3), are 5 × (0.6, 0.8) and 0.5 × (−0.8, 0.6). They are perpendicular, so these are G's singular directions, with singular values 5 and 0.5. Orthogonalizing keeps both directions and sets both strengths to 1. The step rescales O anyway (by η and, below, a shape factor), so what matters is the ratio of strengths: it falls from 10 to 1, and the weak direction now moves as far as the strong one (Figure 8.1).

What orthogonalization does to a 2×2 update A · update G B · orthogonalized O = UVᵀ 5 × (0.6, 0.8) 0.5 × (−0.8, 0.6) 1 × (0.6, 0.8) 1 × (−0.8, 0.6) unit circle strong ÷ weak = 10 strong ÷ weak = 1 Each panel is drawn so its longer arrow has the same length. The step rescales O anyway, so only the ratio matters.
Figure 8.1. The columns of the toy update G and of its orthogonalized form O: same directions, equal lengths.

In general, the singular value decomposition M = UΣV⊤ splits a matrix into directions (U, V) and strengths (the singular values in Σ). Muon's update is UV⊤: every singular value becomes 1, so every direction moves by the same amount, including "rare directions" that Jordan suspects matter for learning.

Mt = μMt−1 + Gt,    Ot = NS(Mt) ≈ UV⊤,    Wt = Wt−1 − ηOt,    W, G, M, O ∈ ℝA×B

In practice Muon orthogonalizes the Nesterov form μMt + Gt instead of Mt: it looks one momentum step ahead, which Jordan found works a bit better in every case he tested, and Moonlight and DeepSeek V4 do the same. The pseudocode below follows that form.

Newton–Schulz: orthogonalizing with matrix multiplies

An SVD every step would be too slow. A Newton–Schulz iteration reaches nearly the same UV⊤ without computing U or V, by repeating one step built from matrix multiplies:

Xk = aXk−1 + b(Xk−1Xk−1⊤)Xk−1 + c(Xk−1Xk−1⊤)2Xk−1   ⟹   σ ↦ φ(σ) = aσ + bσ3 + cσ5

Because XX⊤ = UΣ2U⊤, one step applies the odd polynomial φ to every singular value and leaves U and V alone. Two choices make φ pull every singular value toward 1:

  • Start at or below 1. The iteration begins from X0 = M/‖M‖F, which puts every singular value at or below 1, because the Frobenius norm is at least the largest singular value. For σ well above 1 the cσ5 term dominates and the polynomial blows up.
  • Grow small values fast. Jordan tuned (a, b, c) = (3.4445, −4.7750, 2.0315) to make a, the slope at zero, as large as possible, so a small singular value grows about 3.4 times per step. The price is that φ does not settle at exactly 1: the values keep oscillating in a band Jordan puts at [0.7, 1.3], which he found does not hurt the loss, and 5 steps sufficed in his experiments.

The iteration runs stably in bfloat16 and costs little. For an A×B weight with B ≤ A, each of T steps costs at most about 6AB2 FLOPs, while the forward and backward pass costs about 6AB per token, so Jordan bounds Muon's extra FLOPs, as a fraction of the training FLOPs, by T·B / (tokens per batch). That is about 0.5% for a Llama-405B-sized run. Figure 8.2 follows the singular values of a 3×3 example, worked through below.

Singular values of an update before and after Newton–Schulz singular value 0 0.5 0.7 1.0 .971 .736 1.00 .234 .752 1.00 .051 .767 1.00 direction 1 σ = 5.41 in G direction 2 σ = 1.30 in G direction 3 σ = 0.28 in G input G / ‖G‖F after 5 quintic steps after V4 hybrid (8 + 2) largest ÷ smallest input19.0 5 steps1.04 8 + 2 steps1.00
Figure 8.2. Singular values of the 3×3 example matrix G from the worked example below, drawn to scale. Bars are grouped by singular direction (the pair ui, vi), which Newton–Schulz never changes. Five steps with Jordan's coefficients bring all three into the 0.7 to 1.3 band; DeepSeek V4's last two steps with (2, −1.5, 0.5) pull them to 1.

Worked example: Newton–Schulz on a 3×3 matrix

Take G = [[3, 1, 3], [3, 0, 1], [1, 0, 1]] as a stand-in momentum matrix. Its singular values are 5.406, 1.302 and 0.284, so the strongest direction is 19 times the weakest. ‖G‖F = √31 = 5.568, and X0 = G/5.568 has singular values 0.971, 0.234 and 0.051.

One quintic step on the smallest: φ(0.0511) = 3.4445 × 0.0511 − 4.7750 × 0.05113 + 2.0315 × 0.05115 = 0.1760 − 0.0006 + 0.0000 ≈ 0.175, a 3.4× increase. On the largest: φ(0.971) = 3.3445 − 4.3709 + 1.7531 = 0.727, a decrease. Running the full matrix iteration gives the same numbers, step by step:

Stepσ1σ2σ3largest ÷ smallest
0 (X0)0.9710.2340.05119.0
10.7270.7460.1754.3
21.0821.0570.5781.9
30.6910.6821.2001.8
41.1251.1340.9371.2
50.7360.7520.7671.04

The quintic map overshoots and oscillates around 1, roughly inside Jordan's 0.7 to 1.3 band (step 3 dips to 0.68). DeepSeek V4 runs 8 quintic steps, then 2 with (2, −1.5, 0.5). Here step 8 gives 1.131, 1.134 and 1.130, and the two final steps give 1.017 to 1.018 and then 1.000 for all three. The result matches the exact UV⊤ to within 0.0002 in every entry.

Newton–Schulz and one Muon step in code
def newton_schulz(M, steps=5, eps=1e-7):
    a, b, c = 3.4445, -4.7750, 2.0315        # Jordan's quintic coefficients
    X = M / (frobenius_norm(M) + eps)        # all singular values <= 1
    tall = X.shape[0] > X.shape[1]
    if tall:
        X = X.T                              # keep X @ X.T the smaller Gram matrix
    for _ in range(steps):
        A = X @ X.T
        X = a * X + (b * A + c * A @ A) @ X  # sigma -> a*s + b*s^3 + c*s^5
    return X.T if tall else X

def muon_step(W, G, M, lr, mu=0.95, wd=0.1, rms=0.2):
    # W, G, M: [A, B] weight, gradient, momentum buffer
    M = mu * M + G                           # SGD momentum
    O = newton_schulz(mu * M + G)            # Nesterov look-ahead, then orthogonalize
    O = O * rms * sqrt(max(W.shape))         # update RMS ~ rms, as for AdamW (Moonlight)
    W = W * (1 - lr * wd) - lr * O           # decoupled weight decay, then step
    return W, M

Which parameters stay on AdamW

Muon is defined for 2D weight matrices, so scalars and vectors such as RMSNorm gains and biases stay on AdamW. Jordan also found that the embedding and the output head, though 2D, train best with AdamW. Moonlight keeps "RMSNorm, LM head, and embedding parameters" on AdamW, DeepSeek V4 adds mHC's static biases and gating factors to that list, and MAI-Base-2 runs Muon on its "non-embedding 2D parameters". GLM-4.5 lists only word embeddings, biases and RMSNorm weights as non-Muon parameters. DeepSeek V4.1-Flash adds Engram, a conditional memory: huge embedding tables indexed by hashes of the last 2 to 4 tokens, whose looked-up vectors are gated into the hidden state. It trains those tables, its embeddings and its prediction head with a "Sinkhorn-balanced" momentum update instead of Adam, which needs one state buffer instead of Adam's two. Qwen3.8-Flash-Next has a similar hashed memory, 51B parameters of n-gram embedding tables, trained with Adam without weight decay, and keeps its embeddings, output head, MoE router and gates on AdamW.

Moonlight: making Muon work at scale

Muon set speed records on small models. Kimi's Moonlight report found two problems at scale:

  • Weights grow. Without weight decay the RMS of the weights and layer outputs kept growing, "exceeding the high-precision range of bf16". Adding AdamW-style decoupled weight decay fixed it.
  • Update size depends on shape. For a full-rank A×B matrix, UV⊤ has min(A, B) singular values equal to 1, so its squared Frobenius norm is min(A, B), spread over A·B entries: its RMS is √(min(A, B)/(A·B)) = 1/√max(A, B). A 100×400 matrix gets an update RMS of 1/20 = 0.05 and a 100×100 matrix 1/10 = 0.1. Wide MLP matrices get tiny updates and small per-head matrices get large ones.

Moonlight multiplies each update by 0.2·√max(A, B), which puts every update's RMS near 0.2 (for the 100×400 matrix, 0.05 × 0.2 × 20 = 0.2), inside the 0.2 to 0.4 range AdamW's updates already have:

Wt = Wt−1 − ηt ( 0.2 · Ot · √max(A, B) + λWt−1 ),    Ot ∈ ℝA×B

Muon can then reuse the learning rate and weight decay tuned for AdamW. In Moonlight's scaling-law fits, Muon matched AdamW with about 52% of the training FLOPs, which the paper calls "∼2× computational efficiency". Kimi K2 calls this recipe plus QK-Clip (Chapter 10) MuonClip.

The recipe spread:

Per-head Muon

Jordan's post had already reported that Muon works better on Q, K and V separately than on one fused QKV matrix. The 2026 models go one level further. A projection such as WQ stacks all heads in one matrix, and orthogonalizing it as a whole couples them. In Kimi K3's words, heads with larger gradient or momentum scales "dominate the shared update direction, while smaller-scale heads receive insufficiently normalized updates". Splitting the momentum along the head dimension and orthogonalizing each head's block separately gives every head the same update scale.

Three labs adopted versions of this within seven months. GLM-5's Muon Split orthogonalizes the per-head slices of the MLA up-projections, which closed MLA's gap to GQA in their ablation and kept attention-logit scale stable without any clipping. Kimi K3's Per-Head Muon does it for Q, K and V, and notes that the tall per-head blocks also make Newton–Schulz slightly cheaper. DeepSeek V4.1-Flash's head-wise Muon splits the Query and Key weights; DeepSeek describes it as one preconditioner per head instead of one for all heads, and found that it "outperforms vanilla Muon".

Adoption

Of the eleven labs that state a pretraining optimizer, seven moved their weight matrices to Muon:

  • Muon. Kimi first, then Z.ai (GLM), StepFun (Step 3.5 Flash, Feb 2026), DeepSeek, Thinking Machines (Inkling), Qwen (Qwen3.8-Flash-Next, Aug 2026, a preview of its next architecture; Qwen3.5 used AdamW) and Microsoft AI (MAI-Base-2).
  • AdamW, then Muon. Xiaomi still pretrains MiMo-V2.6 with AdamW, then switches the hidden matrices to Muown, a Muon variant, in mid-training, citing Muon's data efficiency for large-batch RL.
  • AdamW. NVIDIA (Nemotron 3) and Ant (Ling 2.0) pretrain with AdamW, and MiniMax last named an optimizer, AdamW, for MiniMax-Text-01.

Figure 8.3 places the main releases on a timeline.

Pretraining optimizer by release date Muon, or a per-head variant, for weight matrices Moonlight Kimi K2 (MuonClip) GLM-4.5 Kimi Linear GLM-5 (Muon Split) DeepSeek V4 Inkling K3 (per-head) DeepSeek V4.1-Flash (head-wise) MAI-Base-2 Jan 2025 Jul 2025 Jan 2026 Jul 2026 AdamW for the whole pretraining run DeepSeek V3 MiMo-7B MiMo-V2-Flash MAI-Thinking-1 MiMo-V2.6 (Muown from mid-training)
Figure 8.3. Pretraining optimizer of the main releases that state one, placed at its release date (to scale). Gemma, gpt-oss, Llama 4, Muse and Mistral do not name theirs; the other labs the atlas added are covered in the text, not drawn. Sources: the optimizer cells of the cross-lab pretraining grid and each lab's report; dates from the lab announcements.

Who uses it and why

"We employ the Muon (Jordan et al., 2024; Liu et al., 2025) optimizer for the majority of modules in DeepSeek-V4 series due to its faster convergence and improved training stability."

"When scaling up to MAI-Base-2, we found that Muon delivered more stable training dynamics and large efficiency gains over AdamW."

"per-head orthogonalization equalizes the update scale across heads."

Trade-offs

  • Newton–Schulz needs whole matrices. In sharded training, MAI-Base-2 reshards momentum with an all-to-all so each GPU orthogonalizes full matrices; after optimization Muon took 2.1% of iteration time.
  • A hybrid setup means two optimizers and a per-lab choice of which parameters go where; RMS matching is what lets them share one learning rate.
  • Kimi saw attention logits explode more often with Muon than with AdamW, and hypothesizes that Muon's full-rank updates make a weight matrix's largest singular values more likely to keep growing (Chapter 10).
  • The iteration is not always safe in bfloat16: StepFun traced loss spikes in Step 3.5 Flash to rare bfloat16 outliers and moved only its Polar Express iteration to float16.
  • Switching optimizers mid-run can cause a mismatch; MiMo cites prior work on this risk, though it saw no loss spike when it switched.
  • Muon keeps one momentum buffer per matrix, against Adam's two state tensors, so it saves optimizer memory.

Takeaways

  • Adam scales each coordinate by its own gradient history; Muon replaces a matrix's momentum by UV⊤, so every singular direction moves equally.
  • Newton–Schulz applies an odd polynomial to all singular values using only matrix multiplies; Jordan's quintic leaves them oscillating in roughly 0.7 to 1.3, and V4's 8 + 2 schedule reaches 1.
  • Moonlight's weight decay and update-RMS matching made Muon a drop-in for AdamW at scale, and by 2026 GLM, Kimi and DeepSeek orthogonalize attention weights per head.
Check yourself: why does Newton–Schulz start by dividing M by its Frobenius norm?

The coefficients are tuned so that singular values in [0, 1] are pulled toward 1; values well above 1 grow without bound. The Frobenius norm is at least the largest singular value, so the division puts all of them in that range, and it does not change UV⊤, since scaling M leaves U and V unchanged.

Check yourself: a DeepSeek-V4-Pro expert matrix is 7,168 × 3,072. What is the RMS of its raw Muon update, and what factor does V4 apply?

UV⊤ has RMS 1/√max(7168, 3072) = 1/84.7 ≈ 0.0118. V4 multiplies by √7168 × 0.18 ≈ 15.2, giving an update RMS of 0.18. Moonlight's 0.2 would give a factor of about 16.9.

  1. Kingma and Ba. Adam: A Method for Stochastic Optimization (2014).
  2. Loshchilov and Hutter. Decoupled Weight Decay Regularization (2017).
  3. Jordan et al. Muon: An optimizer for hidden layers in neural networks (blog post, Dec 2024).
  4. Liu et al. (Moonshot AI). Muon is Scalable for LLM Training (Moonlight) (2025).
  5. Kimi Team. Kimi K2 technical report, §2.1; Kimi K3 technical report, §2.5, §3.3.
  6. Z.ai. GLM-4.5 report, §2.4; GLM-5 report, §2.1.
  7. DeepSeek-AI. DeepSeek-V4 report, §2.4, §4.2.2; DeepSeek-V4.1 report, §2.5; DeepSeek-V3 report, §4.2.
  8. Microsoft AI. Frontier Pre-training at Microsoft AI (MAI-Base-2); MAI-Thinking-1 report, §2.6.2.
  9. Xiaomi. MiMo-V2.6 report, §3; MiMo-7B report; MiMo-V2-Flash report.
  10. Thinking Machines. Introducing Inkling.
  11. NVIDIA. Nemotron 3 Super report. Ant. Ling 2.0 report. MiniMax. MiniMax-01 report. Qwen. Qwen3.8-Next architecture report.

09 Learning-rate schedules and hyperparameter scaling

How do labs set the learning rate at every step of a trillion-token run, and the batch size and weight decay that go with it, when the final model can be trained only once?

The learning rate η scales every optimizer update. A large η makes fast progress but leaves the weights bouncing in a noisy region; a small η lets them settle. A schedule plans when to do which.

The shapes at a glance

A schedule is assembled from a few pieces (Figure 9.1). Warmup comes first. After it, the shapes differ in when they commit to the run's length:

  • Cosine decays over the whole run, so it needs the final step from the start.
  • Warmup-stable-decay (WSD) holds η constant and decays only at the end, so the end can be chosen late. A minus-square-root decay is a WSD decay that drops fast at first and then flattens.
  • Checkpoint merging never decays: η stays constant to the end, and averaging the weights of the last few checkpoints takes the decay's place.
The pieces of a learning-rate schedule Warmup 1 0 0 100 step 10 warmup steps: step 5 runs at 0.5 × peak Constant 1 0 0 100 step no end date needed: steps 20 and 90 both run at the peak Cosine 1 0 0 100 step needs the final step from the start; halfway, (1 + cos 90°)/2 = 0.5 × peak Warmup-stable-decay (WSD) 1 0 0 100 step decays over the last 10 steps: step 90 at the peak, step 95 at 0.5 × peak Minus-square-root decay 1 0 0 100 step last 20 steps: η = 1 − √f, f = share done; at step 85, f = 0.25 and η = 0.5 × peak Checkpoint merging 1 0 0 100 step average no decay: the final model averages the weights at steps 80, 90 and 100
Figure 9.1. The pieces of a learning-rate schedule on a toy run of 100 steps, with η drawn as a fraction of its peak; warmup is drawn only in the first panel. Illustrative values, not from any lab.

Warmup

Warmup raises η linearly from zero over the first steps; the original Transformer used 4,000. Xiong et al. traced the need to Post-LN blocks (normalization after the residual add), whose gradients near the output are large at initialization, and showed that Pre-LN models can train without it. Labs still warm up: DeepSeek-V3 for 2K steps, Kimi K2 for 500 steps, Kimi K3 for 1% of training, MAI-Base-1 for about 12B tokens.

Cosine decay

The cosine schedule then lowers η along half a cosine wave from the peak ηmax to a floor ηmin at the final step S (s is the current step, W the last warmup step):

η(s) = ηmin + ½ (ηmax − ηmin) · (1 + cos(π · (s − W) / (S − W))),   W ≤ s ≤ S

S must be the true run length. Chinchilla got the best final loss when the cosine length matched the token count, and overshooting it by more than 25% noticeably hurt. A cosine run commits to its budget on day one: mid-run checkpoints still have high η, and training longer means re-warming η (as Moonlight did for its last 0.5T tokens, after a full cosine) or starting over.

Warmup-stable-decay

MiniCPM split training into a long phase at constant η and a short decay, the warmup-stable-decay (WSD) schedule. With T the end of the stable stage and 0 < f ≤ 1 any decreasing function:

WSD(T; s) = (s/W) · η for s < W;   η for W < s < T;   f(s − T) · η for T < s < S

On a 0.036B model, the loss dropped sharply once decay began and reached or beat the cosine run of the same length. Decaying over 10% of total tokens was enough; 2.5% fell short.

The stable phase does not need to know when training ends, so any stable checkpoint can be branched: decay a copy to get a finished model and keep training the original. With a 10% decay, one stable run yields a 6T-token model (5.4T stable tokens, then 0.6T of decay on a copy) and later a 10T-token model (resume to 9T, decay 1T), for 10.6T tokens of compute instead of 16T for two separate runs. MiniCPM measured data scaling this way, with one stable run per model size and decayed branches at several token counts. For m model sizes × m data sizes, this cuts the work from about m2 training runs to about m. A lab can also extend a run by resuming from the last checkpoint before decay.

Cosine, WSD and branching in code
def lr_cosine(s, W, S, peak, floor):
    if s < W:
        return peak * s / W                       # linear warmup
    p = (s - W) / (S - W)                         # 0 -> 1, needs the final step S
    return floor + 0.5 * (peak - floor) * (1 + cos(pi * p))

def lr_wsd(s, W, T, S, peak, floor):
    if s < W:
        return peak * s / W
    if s < T:
        return peak                               # stable: no end date needed
    p = (s - T) / (S - T)                         # short decay, e.g. S - T = 0.1 * S
    return floor + 0.5 * (peak - floor) * (1 + cos(pi * p))  # cosine-shaped decay

# WSD branching: one stable run yields finished models at 6T and 10T tokens
ckpt = train(init(), lr=peak, tokens=5.4e12)      # stable phase
model_6T = decay(copy(ckpt), tokens=0.6e12)       # branch off and decay 10%
ckpt = train(ckpt, lr=peak, tokens=3.6e12)        # resume the stable run to 9T
model_10T = decay(ckpt, tokens=1.0e12)            # total compute: 10.6T tokens

Figure 9.2 puts cosine and WSD on one run, with a branch, and then draws DeepSeek-V3's published schedule to scale.

Cosine vs WSD learning-rate schedules, illustrative and DeepSeek-V3 A · Illustrative values, not from any lab 1% warmup, floor 0.1 × peak, WSD decays over the last 10% η / peak 1.0 0.5 0.1 0% 25% 50% 75% 100% share of the run's training tokens WSD stable phase at peak η decay finished model at 50% cosine, ends at 100% WSD, ends at 100% WSD branch from 45% B · DeepSeek-V3 as published, to scale dashed: plain cosine, same peak and floor (comparison only) η 2.2×10⁻⁴ 1.0×10⁻⁴ 2.2×10⁻⁵ 0 2 4 6 8 10 12 14 training tokens (trillions); run ends at 14.8T constant 2.2×10⁻⁴ until 10T tokens cosine decay over 4.3T last 500B: 2.2×10⁻⁵, then 7.3×10⁻⁶
Figure 9.2. Top: made-up values; the dashed branch decays a copy of the 45% WSD checkpoint into a finished model. Bottom: DeepSeek-V3's published schedule to scale; dashed is a hypothetical full-length cosine.

Who uses which

DeepSeek, Kimi K2 and MiMo use a WSD shape whose decay follows a cosine:

ReleasePeak ηHeld constantDecay
DeepSeek-V32.2×10−4to 10T tokenscosine to 2.2×10−5 over 4.3T, then low constants
Kimi K22×10−4first 10T tokenscosine to 2×10−5 over 5.5T, then to 7×10−6
MiMo-7B1.07×10−410.2T tokenscosine to 3×10−5 over 7.5T, held for 5.5T, then to 1×10−5
DeepSeek V4.1-Flash2.6×10−4to 28T tokenscosine to 2.6×10−5 by 40T, held to 45T

GLM-4.5 chose plain cosine from 2.5×10−4 to 2.5×10−5 because its WSD runs scored worse on SimpleQA and MMLU, which it read as underfitting in the stable stage. MAI-Base-1 decays along a cosine from 2×10−4 to 2×10−5, a 0.1× floor rather than the common 0.01×, because decaying less helped after RL. Kimi used WSD for K2 and moved to cosine for K3 after tuning each schedule separately, since their optimal peak η and batch sizes differ:

"Under their respective optimal hyperparameter settings, cosine decay consistently achieves a lower final loss than WSD."

Two of the labs the atlas added change how the run ends. NVIDIA's Nemotron 3 Super holds its peak for 20T of 25T tokens, then decays along a minus-square-root curve over the last 5T, and the base it hands to post-training is a merge of checkpoints over a 500B-token window. Ant drops the decay entirely: Ling 2.0's warmup-stable-merge (WSM) schedule keeps η constant to the end and gets the annealing effect by merging checkpoints, which for Ling-1T come from its mid-training.

Gemma, gpt-oss, Llama 4, Inkling and Mistral do not publish their schedule shapes.

Worked example: DeepSeek-V3's schedule in numbers

DeepSeek-V3 trained on 14.8T tokens: warmup to 2.2×10−4 over 2K steps; constant until 10T tokens; cosine to 2.2×10−5 over 4.3T; then 2.2×10−5 for 333B tokens and 7.3×10−6 for the last 167B.

Budget: 10 + 4.3 + 0.333 + 0.167 = 14.8T; 10/14.8 = 67.6% of tokens see the peak, 4.3/14.8 = 29.1% the cosine, 0.5/14.8 = 3.4% the tail.

Midway through the cosine (12.15T), cos(π/2) = 0, so η = 2.2×10−5 + ½(2.2×10−4 − 2.2×10−5) = 1.21×10−4; this is also the half-cosine's average. Token-weighted mean η, ignoring warmup: (10 × 2.2 + 4.3 × 1.21 + 0.333 × 0.22 + 0.167 × 0.073) × 10−4 / 14.8 = 27.29×10−4 / 14.8 = 1.84×10−4, or 84% of peak. A plain cosine over all 14.8T with the same peak and floor averages 1.21×10−4, 55% of peak. WSD keeps η high longer and settles late.

Batch size moves too

The batch size B interacts with η, and MiniCPM found that the optimal batch size grows as the loss falls. Labs either ramp B up early in the run or hold it fixed:

Carrying hyperparameters up in scale

The best η, B and weight decay λ shift with model size and token count, and no lab can grid-search them on the final model. Labs take one of two routes:

MAI's rungs are set by the layer count L alone (width d = (256/3)·L, so L78 gives 6,656) and trained at a fixed number of tokens per active parameter (TPP). For MAI-Base-2, Microsoft found the best pair (η*, λ*) at several sizes and TPPs and fit two laws in the number of optimizer steps:

η* · λ* = 17.04 / steps     log η* = −1.51 + 0.175 · log TPP − 0.573 · log steps
  • The product law fixes how long the weights remember. Each step multiplies the weights by (1 − ηλ), so an old weight value fades with a time constant of about 1/(ηλ) steps. The −1 exponent makes this time constant 1/(η*λ*), which Microsoft calls the decoupled weight-decay time scale, a fixed share of training: steps/17.04, about 6%. A 100,000-step run gets η*λ* = 17.04/100,000 ≈ 1.7×10−4, so its weights forget over about 5,900 steps.
  • The learning-rate law nearly reproduces a rule of thumb. The −0.573 exponent on steps is close to the rule that doubling the batch should multiply η by √2: at a fixed token budget, doubling the batch halves the steps, so η* rises by 20.573 ≈ 1.49, near √2 ≈ 1.41.

These laws set MAI-Base-2's hyperparameters, and Kimi K3 likewise retuned batch size, η, TPP and model shape with scaling-law studies.

Small rungs must also see data the way the big run does. MAI's source scaling shrinks the unique data on small rungs so that a dataset repeated 8 times over 50T tokens is looped 8 times over 1/10 of the data in a 5T-token run:

"Without source scaling, experiments at smaller scale can favor under-regularized architecture and hyperparameter choices that overfit at larger scales."

Inkling instead ties weight decay to η:

"We coupled the weight decay strength to the square of the learning rate, which we found kept the overall size of the model weights stable across training horizons"

Trade-offs

  • Cosine fixes the token budget in advance; extending the run needs a re-warm or a new run, and a mid-run checkpoint has not been decayed.
  • WSD checkpoints need a decay (about 10% more tokens per branch) before use, and GLM-4.5 and Kimi K3 each found cosine better in their own comparisons.
  • Fitted laws extrapolate from small runs and mislead if the ladder sees data differently from the target.
  • The η that minimizes pretraining loss may not be best after RL, as MAI's higher floor shows.

Takeaways

  • Cosine fixes the run length in advance; WSD holds η constant so any checkpoint can be decayed (about 10% more tokens) into a finished model.
  • DeepSeek and Kimi K2 hold the peak for 60-70% of the run, MiMo for about 40% and Nemotron 3 Super for 80%, then decay; GLM-4.5, MAI-Base-1 and Kimi K3 use full cosine, and Ant replaces the decay with checkpoint merging.
  • Hyperparameters are found on small models and carried up by a parameterization (μP, MetaP) or by laws fitted on ladders that repeat data like the target run (MAI-Base-2).
Check yourself: why can't a lab ship the 50% checkpoint of a 20T-token cosine run as a 10T-token model?

At the midpoint of a cosine with a 0.1× floor, η is still (1 + 0.1)/2 = 55% of peak, so the weights never got the decay that produces the late loss drop. Its cosine is 100% longer than its 10T of training, far past Chinchilla's harmful 25% overshoot. With WSD, the lab would decay a copy of a 9T stable checkpoint for 1T tokens.

Check yourself: under MAI-Base-2's laws, a run doubles its step count at fixed TPP. How do η* and λ* change?

η* scales by 2−0.573 ≈ 0.672. The product η*λ* halves, so λ* scales by 0.5 / 0.672 ≈ 0.744.

  1. Hu et al., MiniCPM: Unveiling the Potential of Small Language Models with Scalable Training Strategies (2404.06395)
  2. Hoffmann et al., Training Compute-Optimal Large Language Models (Chinchilla, 2203.15556)
  3. Vaswani et al., Attention Is All You Need (1706.03762)
  4. Xiong et al., On Layer Normalization in the Transformer Architecture (2002.04745)
  5. DeepSeek-V3 Technical Report, §4.2-4.3
  6. DeepSeek-V4.1-Flash Technical Report, §4.2.2
  7. Liu et al., Muon is Scalable for LLM Training (Moonlight), §3.3
  8. Kimi K2: Open Agentic Intelligence, §2.5
  9. Kimi K3 Technical Report, §3.2-3.3
  10. GLM-4.5 Technical Report, §2.4
  11. MiMo-7B Technical Report, §2.3
  12. MAI-Thinking-1 / MAI-Base-1 report, §2.2.1 and §2.6.2
  13. Frontier Pre-training at Microsoft AI (MAI-Base-2), PDF and blog version
  14. Meta, The Llama 4 herd (blog), §Pre-training
  15. Thinking Machines, Introducing Inkling

10 Training stability

What makes a long pretraining run's loss spike or diverge, and how did Kimi K2 train 15.5T tokens with Muon "without a single loss spike"?

What instability looks like

A loss spike is a sudden jump in training loss, usually together with a jump in gradient norm. Some spikes recover on their own; others keep rising until training diverges and never comes back. Either way they waste compute: the steps inside the spike teach the model little, and the usual repair is to roll back to an earlier checkpoint and redo work.

Where instabilities start

A spike begins when some quantity grows past what the model or the number format can absorb. The reports point to five places where that growth starts, each with its own guards:

Where it startsWhat growsGuards
Logitsattention scores; output and router logits drift upwardQK-norm, QK-Clip, soft-capping, z-loss
Activationsoutliers in MoE layers, amplified by routingclamped or tanh-bounded activations, Anticipatory Routing, gates
Gradientsone example's gradient swamps the batchglobal clipping, activation-gradient clipping, per-layer clamps
Optimizer updatesWq and Wk under Muon; Kimi's hypothesis is that its full-rank updates push up their largest singular valuesQK-Clip after each step, per-head Muon, update clipping
Numericsroundoff, worse for large values and fewer bitsFP32 sums, z-loss, sensitive layers in BF16 or FP32 (chapter 11)

The sections below follow the rows in order; published incidents come after them.

Attention logits: why they grow

Softmax turns attention scores into weights. With four keys and logits (2, 0, 0, 0), the top key gets weight e2 / (e2 + 3) = 0.71. At (20, 0, 0, 0) it gets all but 6 × 10−9. When one logit is far above the rest, softmax becomes one-hot and stops passing gradient to the other keys.

The attention logit between query position t and key position s in head h is qt·ks/√dh. Kimi bounds it by the sizes of the inputs and of the two projection matrices:

|qt · ks| ≤ ‖xt‖ ‖xs‖input norms · ‖Wq‖2 ‖Wk‖2spectral norms

Here x is a token's input to the layer, and a matrix's spectral norm ‖W‖2, its largest singular value, is the most it can stretch a vector. RMSNorm keeps the x terms bounded, so growth comes from the spectral norms of Wq and Wk, and since the logit uses their product, any growth is compounded.

Muon makes the growth worse; this is the optimizer row of the table. Its updates have equal singular values (full rank), while Adam's are dominated by a few directions, and Kimi's hypothesis is that full-rank updates are more likely to line up with a weight's own singular directions and push its largest singular values up. Moonlight already showed max logits above 100 in some layers early in training. In a 9B-active, 53B-total MoE trained with vanilla Muon, max logits "quickly exceed a magnitude of 1000", and K2 adds that "Max logits at this level usually result in instability during training, including significant loss spikes and occasional divergence."

QK-Clip

QK-Clip is Kimi's answer. It watches each head's largest logit and, when that passes a threshold τ, shrinks the head's query and key weights just enough to bring it back. In each training step:

  1. the forward pass records each head's largest logit over the batch, Shmax;
  2. the optimizer takes its usual Muon step;
  3. every head with Shmax above τ has its query and key weights scaled down so that its logits shrink by γh = τ / Shmax.
Shmax = (1/√dh) · maxX∈B maxt,s Qht Kh⊤s     γh = min(1, τ / Shmax)
Whq ← γhα Whq,   Whk ← γh1−α Whk,   α = ½

With α = ½ each matrix shrinks by √γh. The forward and backward pass of the current step are not changed. Clipping is per head because "only a small subset of heads exhibit exploding logits".

Why not a standard remedy? QK-norm (Chapter 5) needs explicit keys, and the keys of MLA, K2's attention, "are not fully materialized during inference". A logit soft-cap bounds the logit after the dot product, but "the dot products between queries and keys can still grow excessively before capping is applied." QK-Clip acts on the weights instead. MLA needs one adjustment, because each head's logit is a content part qC·kC plus a rotary part qR·kR: K2 scales the head-specific content parts qC and kC by √γ, scales the head-specific rotary query qR by γ, and leaves the rotary key kR alone because every head shares it.

QK-Clip in code
def qk_clip(attn_layers, tau=100.0):
    # Runs right after the Muon update. S_max[h] was recorded in this
    # step's forward pass: max over the batch of q_t . k_s / sqrt(d_h).
    for layer in attn_layers:
        for h in range(layer.num_heads):
            s = layer.S_max[h]
            if s <= tau:
                continue                       # most heads, most steps
            gamma = tau / s                    # logits of head h shrink by gamma
            if layer.is_mla:
                layer.W_qc[h] *= sqrt(gamma)   # head-specific content query
                layer.W_kc[h] *= sqrt(gamma)   # head-specific content key
                layer.W_qr[h] *= gamma         # head-specific rotary query
                # W_kr (rotary key) is shared by all heads: left unchanged
            else:
                layer.W_q[h] *= sqrt(gamma)
                layer.W_k[h] *= sqrt(gamma)

K2 ran with τ = 100. Max logits rose to the cap early and stayed there; 12.7% of heads triggered QK-Clip at least once in the first 70,000 steps, after which every head stayed below 100 and the clip stopped firing. K2 pretrained on 15.5T tokens without a loss spike. In a small ablation with an aggressive τ = 30, the loss curve was almost unchanged. Kimi K3 keeps "the weight-clipping mechanism introduced in Kimi K2". Kimi calls the whole optimizer, Muon with weight decay and update-RMS matching (Chapter 08) plus QK-Clip, MuonClip. Figure 10.1 contrasts the two runs.

Max attention logit with and without QK-Clip (schematic) Vanilla Muon, 9B-active / 53B-total MoE Kimi K2 with MuonClip, τ = 100 max attention logit max attention logit 0 400 800 1200 0 5k 10k 15k training steps 1,000 0 50 100 0 50k 100k 150k 200k training steps τ = 100 70k steps: last clip held at τ by QK-Clip Schematic: curve shapes are illustrative. Axis ranges, τ = 100, the 1,000 level and the 70k-step mark come from the Kimi K2 report (Fig. 2, App. D).
Figure 10.1. Max attention logit over training, redrawn as a schematic of Kimi K2's Figure 2. Left: a mid-scale vanilla Muon run passes 1,000. Right: in K2, QK-Clip holds the max logit at τ = 100 early on; after 70,000 steps every head is below τ and the clip no longer acts. The two panels have different axes.

Worked example: one QK-Clip step

Suppose head h of an MLA layer records Shmax = 125 in a step, with K2's τ = 100 (the 125 and its 90 + 35 split below are illustrative). Then γ = τ / Smax = 100 / 125 = 0.8 and √γ = 0.894.

Part of the max logitBeforeScalingAfter
Content: qC · kC900.894 × 0.894 = 0.872
Rotary: qR · kR350.8 × 1 (kR shared, untouched)28
Total logit1250.8100 = τ (same batch, same weights)

Both parts shrink by exactly γ, so with the weights and batch that produced the 125, the max logit would land exactly on τ. QK-Clip runs after the same step's Muon update, which has already moved the weights a little, so the head's next max logit is only near τ. If qR were scaled only by √γ, the rotary part would become 35 × 0.894 = 31.3 and the total 103.3, still above τ. For a plain multi-head layer the result is the same: Wq and Wk each shrink by 0.894. Had a head been allowed to reach 1,000, the level of the vanilla run, γ would be 0.1 and each matrix would lose 1 − √0.1 = 68% of its scale in one step. Because QK-Clip runs every step from the start, a head only drifts one update past τ before it is pulled back.

Logit soft-capping

Soft-capping bounds a logit smoothly: logit ← cap · tanh(logit / cap). Values well below the cap pass almost unchanged and large values approach ±cap. With cap 50, logits of 10, 100 and 1,000 become 9.87, 48.2 and 50.0. Gemma 2 used cap 50 on attention logits and 30 on the final output logits. Gemma 3 replaced Gemma 2's soft-capping with QK-norm, while Meta's Muse Glimmer sets final_logit_softcapping = 20.0 in its config. The cost is gradient: the derivative of a soft-cap is 1 − tanh²(logit / cap), which falls toward zero near the cap (0.07 at a logit of 100 under cap 50), so a capped value receives almost no gradient.

z-loss: output and router logits

Softmax depends only on differences between logits, so a whole logit vector can drift upward without changing the loss, and nothing in the loss pulls it back. Large values are a precision hazard: ST-MoE notes that bfloat16 roundoff can be up to 65,536× worse than float32, and roundoff grows with magnitude. PaLM adds an auxiliary z-loss of 10−4 · log2Z, where Z = ∑j exp(logitj) is the output softmax normalizer, to keep log Z near 0. ST-MoE applied the idea to the router of an MoE layer, whose logits xij score expert j for token i in a batch of B tokens and E experts:

Lz = (1/B) ∑i=1B ( log ∑j=1E exij )2,    x ∈ ℝB×E router logits

It joins the training loss with a small weight:

L = LCEcross-entropy + cBLBload balancing (ch 02) + czLzrouter z-loss,   cz = 0.001

ST-MoE compared it with the blunter alternative of tightening the update clipping in Adafactor, the memory-saving optimizer it trained with. Quality is negative log perplexity on English, so higher is better:

SettingStable runsQuality
Baselineonly 4 of 6−1.755
Router z-loss3 of 3−1.741, slightly better
Tighter Adafactor update clipping3 of 3−4.206, wrecked

Outlier activations in MoE layers

Activations can blow up too, and the MoE reports describe two kinds of guard:

  • Bound the activation. DeepSeek-V4's SwiGLU clamping clamps the linear part to [−10, 10] and caps the gate at 10. Kimi K3 applies the soft-cap's tanh shape inside its MoE activation (SiTU-GLU) "to suppress activation explosion".
  • Break the loop through routing. DeepSeek's reasoning is that routing itself amplifies the outliers, a "vicious cycle". Anticipatory Routing computes the routing from earlier parameters θt−Δt, which decouples the routing decision from the weights being updated and so breaks that loop. It is switched on automatically, with a short rollback, when a spike appears. DeepSeek adds that the mechanism is not yet fully understood.

Gradient clipping and activation-gradient clipping

Global gradient clipping rescales the whole gradient when its norm exceeds a threshold c: g ← g · min(1, c / ‖g‖). DeepSeek-V3, MiMo-7B, MiMo-V2-Flash, MAI-Thinking-1 and PaLM all use c = 1.0. Its weakness is that one bad example shrinks the gradient of the whole batch. If the well-behaved examples give a gradient of norm 0.5 and one outlier adds norm 50, clipping at c = 1 divides everything by about 50 and the useful part shrinks to 0.01. Two narrower guards limit the outlier instead:

  • Activation-gradient clipping. MAI-Base-2 also clips the gradients of activations at selected places in the network, which limits the backward signal of individual tokens. Together with Muon, this kept MAI-Base-2's gradient norm in a much tighter range than MAI-Base-1's, and the benefit grew with scale, to a +28% efficiency gain on held-out evaluations at the largest size of their scaling ladder. The clipped tokens double as a data probe: one led MAI to a preprocessing bug that had cut a license header mid-sentence.
  • Per-layer clamps. StepFun's Step 5 Preview is narrower still: against gradient spikes it clamps only the largest 0.00004% of gradient values in each layer.

Spikes in published runs

Read against the table, most published incidents have a clear origin; some do not.

  • PaLM 540B: data and parameter state together. Google saw spikes "roughly 20 times during training, despite the fact that gradient clipping was enabled", at irregular intervals and sometimes late in the run. The fix was to restart from a checkpoint about 100 steps before the spike and skip 200 to 500 batches. Each rollback repeats at least the 100 steps before the spike; at PaLM's batch sizes of 1M to 4M tokens, that is 0.1B to 0.4B tokens per spike, or 2B to 8B over 20 spikes, up to about 1% of the 780B-token run. Replaying the same batches from an earlier checkpoint did not spike, so the authors concluded that spikes come from "the combination of specific data batches with a particular model parameter state."
  • MAI-Base-1: routing imbalance. Several early spikes recovered without intervention; they mostly hit coding data and correlated with "high expert imbalance under dropless routing" (dropless: no per-expert capacity limit, so every routed token is processed even when a few experts receive most of them).
  • DeepSeek-V4: activations. Rollbacks "do not prevent the recurrence of loss spikes"; DeepSeek tied the spikes to outliers in the MoE layers and added the two activation guards above.
  • Nemotron 3 Ultra: numerics, then unknown. NVIDIA's run diverged twice: at about 8T tokens because gradient accumulation for the output layer had dropped from FP32 to BF16, fixed by going back to FP32, and near 16T for a reason NVIDIA could not determine, after which it annealed early from the 15T checkpoint and cut the run to 20T tokens.

Removing the cause

The newest designs try to keep logits bounded without a clip. DeepSeek V4 applies RMSNorm to its queries and compressed KV entries and so does "not employ the QK-Clip technique". GLM-5's per-head Muon Split keeps "the scale of attention logits" stable "without any clipping strategy". Gemma 3 and 4, GLM-4.5 and MAI-Thinking-1 use QK-norm. Qwen relies on gates: an attention output gate in Qwen3-Next removed attention sinks and massive activations, and Qwen3.8-Flash-Next trained without a single loss spike and without QK-Clip or SwiGLU clipping, which Qwen credits largely to the gate in its Gated Residual (chapter 05).

Who uses it and why

"scaling up Muon training reveals a challenge: training instability due to exploding attention logits, an issue that occurs more frequently with Muon but less with AdamW in our experiments."

"An outlier can therefore cause the gradients from the entire batch to be scaled down, including contributions from otherwise well-behaved examples."

"Empirically, we identified that the occurrence of spikes is consistently tied to outliers in the MoE layers, and the routing mechanism itself appears to exacerbate the emergence of these outliers."

Trade-offs

  • QK-Clip needs every head's max logit from the forward pass, edits weights outside the optimizer, and reacts one step after a head crosses τ; τ is one more hyperparameter.
  • Soft-caps give almost no gradient near the cap, and the q·k product underneath can keep growing.
  • z-loss adds a coefficient to tune and one more loss term computed for every token.
  • Global gradient clipping scales down the whole batch for one outlier; activation-gradient clipping needs chosen sites and thresholds.
  • Rollbacks and skipped batches repeat compute; V4's Anticipatory Routing adds about 20% wall-clock time while it is switched on.

Takeaways

  • Spikes start in one of five places (logits, activations, gradients, optimizer updates, numerics), and each guard bounds one quantity in one of them: attention, output and router logits, MoE outliers, outlier gradients.
  • Muon makes attention logits grow faster. After each step, K2's QK-Clip shrinks an offending head's logits by γ = τ / Smax: √γ on Wq and Wk in plain multi-head attention, and in MLA √γ on qC and kC, γ on qR, with the shared kR untouched. It switched itself off after 70,000 steps.
  • Newer models prefer to remove the cause (QK-norm in V4, Muon Split in GLM-5, output gates at Qwen) or to clip narrowly (MAI's activation gradients, StepFun's per-layer gradient clamp) over global measures.
Check yourself: in MLA, why does QK-Clip scale qR by γ but qC and kC only by √γ?

The content logit is qC·kC, so scaling both by √γ scales it by γ. The rotary key kR is shared by all heads and cannot be scaled for one head without changing the others, so the full factor γ goes on that head's qR. Both parts then shrink by γ.

Check yourself: if every output logit is shifted up by 10, what happens to the cross-entropy loss and to PaLM's z-loss?

Cross-entropy is unchanged, because softmax ignores a common shift. log Z rises by 10, so if log Z was 0 the z-loss goes from 0 to 10−4 × 102 = 0.01, and its gradient pushes the logits back down.

  1. Kimi Team. Kimi K2: Open Agentic Intelligence, §2.1, App. D, App. E (2025).
  2. Liu et al. (Moonshot AI). Muon is Scalable for LLM Training (Moonlight), App. D (2025).
  3. Chowdhery et al. PaLM: Scaling Language Modeling with Pathways, §5, §5.1 (2022).
  4. Zoph et al. ST-MoE: Designing Stable and Transferable Sparse Expert Models, §3 (2022).
  5. Gemma Team. Gemma 2 report, §2; Gemma 3 report, §2.
  6. Microsoft AI. Frontier Pre-training at Microsoft AI (MAI-Base-2); MAI-Thinking-1 report, §2.6.
  7. DeepSeek-AI. DeepSeek-V4 report, §2.4, §4.2.3; DeepSeek-V3 report, §4.2.
  8. Kimi Team. Kimi K3 technical report, §2.3, §3.3. Z.ai. GLM-5 report, §2.1.
  9. Meta. Muse Glimmer config.json. Xiaomi. MiMo-7B report; MiMo-V2-Flash report.
  10. NVIDIA. Nemotron 3 Ultra report. StepFun. Inside Step 5 Preview. Qwen. Qwen3-Next blog; Qwen3.8-Next architecture report.

11 Low-precision training

How do labs run the matrix multiplies of pretraining on 8-bit numbers without the loss drifting away from a 16-bit run?

Why the number of bits matters

Fewer bits per number mean less memory, less bandwidth, and more multiply-adds per second from tensor cores, the GPU's matrix-multiply units. DeepSeek says that running its GEMMs (general matrix multiplications) in 8-bit floating point, FP8, theoretically doubles the computational speed of 16-bit BF16. Memory adds up: Kimi K2's BF16 parameters plus an FP32 gradient buffer take about 6 TB, which is 1.04 trillion parameters times 2 + 4 bytes.

What a floating-point number stores

A floating-point number has a sign bit, exponent bits that set its range, and mantissa bits that set its precision between two powers of two: with m mantissa bits, each such span holds 2m evenly spaced values. BF16 has 7, so it stores 0.1 as 0.10009765625.

FP16 (1, 5 and 10 bits) has a narrow range: its normal values run from 6.10×10−5 to 6.55×104, so FP16 training needs loss scaling, a multiplier on the loss that keeps small gradients from underflowing. BF16 keeps FP32's 8 exponent bits with a 7-bit mantissa, so it covers FP32's range without loss scaling. Figure 11.1 draws the layouts to scale.

Floating-point bit layouts, one cell per bit sign exponent (range) mantissa (precision) largest value FP32 8 23 max 3.40×10³⁸ BF16 8 7 max 3.38×10³⁸ FP16 5 10 max 6.55×10⁴ FP8 E5M2 5 2 max 57,344 FP8 E4M3 4 3 max 448 FP4 E2M1 2 1 max 6 · MXFP4 and NVFP4 element
Figure 11.1. Bit layouts to scale, one cell per bit; largest values from the bfloat16, FP8 and MX papers.

The standard recipe feeds BF16 tensors to each GEMM, accumulates in FP32, and keeps an FP32 master copy of the weights for the optimizer.

Two FP8 formats

The FP8 formats paper (NVIDIA, Arm, Intel) splits 8 bits two ways: E4M3 (4 exponent bits, 3 mantissa bits) and E5M2 (5 and 2). E5M2 follows IEEE conventions and reaches 57,344. E4M3 drops infinities and keeps one NaN pattern to gain a power of two: it spans 2−9 to 448. The paper recommends E4M3 for weights and activations, E5M2 for gradients. A stored value decodes as

v = (−1)Ssign · 2E − biasexponent · (1 + M / 2m)mantissa,   bias = 7 (E4M3) or 15 (E5M2),   m = mantissa bits

With 3 mantissa bits, E4M3 holds only 1, 1.125, 1.25, …, 1.875 between 1 and 2, so rounding costs at most 1/16 (6.25%) of a value. Below the smallest normal value, 2−6, numbers are subnormal: they sit on a fixed grid of spacing 2−9, so relative error grows as values shrink.

In simulated FP8 (inputs rounded, arithmetic in 16-bit), the paper matched 16-bit GPT training up to 175B parameters, perplexity 6.68 against 6.65. It relied on a scaling factor, chosen so that a tensor's largest magnitude lands near the format's maximum, then divided out after the GEMM. How finely that scale is chosen is what separates the FP8 recipes below.

One scale per tensor, or one per block

The simplest choice is one scale per tensor, s = 448 / max|x|, often with delayed scaling, which infers the maximum from earlier steps. Here s multiplies values before rounding and is divided out after the GEMM. The weakness is outliers, which DeepSeek says often limit low-precision training. One huge value sets max|x| and shrinks the scale for everything else. Any value more than 448 / 2−6 = 28,672 times below the maximum falls among the subnormals or rounds to zero.

The cure is one scale per small block, so an outlier shrinks only its own block's scale. Block formats differ in block size and in how the scale is stored:

  • FP8 with FP32 block scales. DeepSeek-V3 scales activations per 1×128 tile (one token, 128 channels) and weights per 128×128 block, with E4M3 values and FP32 scales computed online from the current values.
  • MXFP8 and MXFP4. The Microscaling (MX) formats, an Open Compute Project standard, build the block into the format. An MX block holds 32 elements and one shared 8-bit E8M0 scale, an exponent-only number and so a power of two. MXFP8 has E4M3 or E5M2 elements; MXFP4 has 4-bit E2M1, which can hold only 0, 0.5, 1, 1.5, 2, 3, 4 and 6 and their negatives.
  • NVFP4. NVFP4 stores E2M1 values with an FP8 E4M3 scale per 16 elements and one FP32 scale per tensor.
FormatValues per scaleScaleBits per value
FP8, one scale per tensorwhole tensorFP328
FP8, DeepSeek-V3 blocks128 (activations), 16,384 (weights)FP328.25 (activations), about 8 (weights)
MXFP832E8M0, a power of two8.25
MXFP432E8M0, a power of two4.25
NVFP416E4M3, plus FP32 per tensor4.5

DeepSeek's FP32 scale is 448 / max|x| over each block. MX picks a power of two instead and divides by it:

sblk = 2⌊log2 maxi |Vi|⌋ − emax,   qi = quantize(Vi / sblk),   vi = sblk · qi,   i = 1 … 32

The shared scale sblk divides the block's values before rounding. emax is the exponent of the element format's largest normal value: 8 for E4M3, since 448 = 1.75 · 28, and 2 for E2M1, since 6 = 1.5 · 22. The scale adds 8 / 32 = 0.25 bits per element, which is why gpt-oss counts its MXFP4 weights as 4.25 bits per parameter. A power of two is cheap to apply but coarser than an FP32 scale. Quantizing and transposing do not commute: the backward pass multiplies by W⊤, whose 32-element blocks run along the other dimension, so training keeps separately quantized copies of a weight and its transpose.

Worked example: one toy block, five ways

Eight illustrative activations in two blocks of four (standing in for 1×128 tiles or 32-element blocks): A = [0.012, −0.0071, 0.0033, 0.0185], B = [0.021, −0.0094, 640, 0.0047]. Each scheme scales, rounds and divides back.

One tensor scale (FP8): s = 448 / 640 = 0.7. Then −0.0071 × 0.7 = −0.00497 < 2−6 = 0.0156, so it rounds on the subnormal grid 2−9 = 0.00195: 0.00497 / 0.00195 = 2.54 → 3 steps = 0.00586, and 0.00586 / 0.7 = 0.00837. Error 17.9%.

Own FP32 scale for A (FP8): sA = 448 / 0.0185 = 24,216. Then 0.0071 × 24,216 = 171.9, in [128, 256) where E4M3 steps are 27−3 = 16: 171.9 / 16 = 10.75 → 11 → 176, and 176 / 24,216 = 0.00727. Error 2.4%.

Power-of-two scales (MX): for E4M3 the scale is 2⌊log2 0.0185⌋ − 8 = 2−6 − 8 = 2−14, so dividing by it multiplies by 16,384 instead of the FP32 scale's 24,216. For E2M1 it is 2−6 − 2 = 2−8, and 0.0185 / 2−8 = 4.74 rounds to 4, so even the block's largest value loses 15.5%.

NVFP4: with scale 0.0185 / 6 (ignoring the scale's own rounding to E4M3), 0.0185 maps exactly to 6, E2M1's largest value, and −0.0071 to −2.30, which rounds to −2.

Block AFP8, tensor scaleFP8, own FP32 scaleMXFP8, ÷ 2−14MXFP4, ÷ 2−8NVFP4, ÷ 0.0185/6
0.0120.01116
(7.0%)
0.01189
(0.9%)
0.01172
(2.3%)
0.01172
(2.3%)
0.01233
(2.8%)
−0.0071−0.00837
(17.9%)
−0.00727
(2.4%)
−0.00732
(3.2%)
−0.00781
(10.0%)
−0.00617
(13.1%)
0.00330.00279
(15.4%)
0.00330
(0.1%)
0.00342
(3.6%)
0.00391
(18.4%)
0.00308
(6.6%)
0.01850.01953
(5.6%)
0.01850
(0.0%)
0.01758
(5.0%)
0.01563
(15.5%)
0.01850
(0.0%)
RMS error8.2%0.85%4.3%13.0%4.3%

The RMS error is the relative √(∑(x̂ − x)² / ∑x²) over block A. Block B keeps scale 0.7 under both FP32-scale schemes (under the MX rule its E4M3 scale is 21): per-block scales confine an outlier's damage to its own block. The FP4 columns show what 4 bits cost in this block: MXFP4's power-of-two scale triples MXFP8's error, and NVFP4's finer scale brings it back to MXFP8's level.

Block scales inside a matrix multiply

A matrix multiply sums over the inner dimension K: Y[m, n] = ∑k xmkwkn. One scale per row of X and per column of W is constant along that sum and can be divided out afterwards. DeepSeek's scales change every 128 channels along K, cannot be factored out, and so cannot be applied by standard FP8 GEMMs. DeepSeek applies them during accumulation instead, slice by slice.

The hardware gives a second reason to split the sum. H800 tensor cores keep only about 14 bits in FP8 sums, which gave a maximum relative error of nearly 2% at K = 4096. So every NC = 128 elements, partial sums move to FP32 registers on the CUDA cores (the general-purpose units), where they are unscaled and summed. Figure 11.2 draws one such GEMM.

Per-tile and per-block scales in an FP8 GEMM Activations X [M × K] K = 512 channels = 4 tiles of 128 s_x 6 tokens shown; each row is one token (row height not to scale) 1×128 tile: one scale per token per 128 channels Weights W [K × N] N = 768 outputs = 6 blocks of 128 s11 s12 s13 s14 s15 s16 s21 s22 s23 s24 s25 s26 s31 s32 s33 s34 s35 s36 s41 s42 s43 s44 s45 s46 K = 512 = 4 blocks of 128 128×128 block: 16,384 weights share one scale, s = 448 / max |w| over the block Y = X · W, summed over K for each 128-slice κ of K: tensor cores: Σ q_x · q_w copy partial sum to FP32 multiply by 1/(s_x · s_w), add highlighted: tile 3 meets block row 3 One 1×128 tile enlarged 6×, split the MX way 32 × E4M3 32 × E4M3 32 × E4M3 32 × E4M3 MXFP8: 32 elements per block one shared 8-bit E8M0 scale (a power of two) per block
Figure 11.2. DeepSeek-V3's FP8 GEMM, drawn to scale along K (token rows thickened). Tile κ and block row κ cover the same 128 channels, so their scales are removed together once per slice. Bottom: MX's 32-element blocks.
Y[m, n] = ∑κ = 1K/128 (sx[m, κ] · sw[κ, ⌈n/128⌉])−1undo both scales, in FP32 · ∑k ∈ κ qx[m, k] · qw[k, n]FP8 slice sum on tensor cores
X, qx ∈ ℝM×K,   W, qw ∈ ℝK×N,   sx ∈ ℝM×K/128,   sw ∈ ℝK/128 × N/128
Block quantization and the sliced GEMM in code
def quantize_x(X):                        # X: [M, K] activations
    T = X.reshape(M, K // 128, 128)       # 1x128 tiles
    s = 448.0 / T.abs().amax(-1)          # [M, K/128], one scale per tile
    return to_e4m3(T * s[..., None]).reshape(M, K), s

def quantize_w(W):                        # W: [K, N] weights
    B = W.reshape(K // 128, 128, N // 128, 128)    # 128x128 blocks
    s = 448.0 / B.abs().amax((1, 3))      # [K/128, N/128]
    return to_e4m3(B * s[:, None, :, None]).reshape(K, N), s

def fp8_gemm(Xq, sx, Wq, sw):             # returns Y: [M, N] in FP32
    Y = zeros(M, N, dtype=fp32)
    for k in range(K // 128):             # one 128-wide slice of K
        cols = slice(128 * k, 128 * (k + 1))
        P = Xq[:, cols] @ Wq[cols, :]     # tensor cores, ~14-bit sums
        sw_k = sw[k].repeat_interleave(128)          # [N]
        Y += P / (sx[:, k, None] * sw_k[None, :])    # FP32 on CUDA cores
    return Y

Small groups let DeepSeek use E4M3 even for gradients, as grouping effectively shares exponent bits: each group's scale acts as a shared exponent, so an element's own exponent only covers the range inside its group, where E4M3's 4 bits suffice. Embedding, output head, MoE gating, normalization and attention stay in BF16 or FP32. The tile shape matters: with 128×128 blocks for activation gradients, a 16B MoE diverged after about 300B tokens, which DeepSeek hypothesizes comes from token-correlated outliers. Against BF16 runs at about 16B and 230B parameters, the final recipe stayed below 0.25% relative loss error.

Who trains in which format

The published pretraining recipes sort into five groups:

GLM-5, Gemma 4, Inkling, Qwen3, MiniMax and Mistral do not state their pretraining precision.

FP4 is mostly a post-training format

Four-bit formats enter mainly through quantization-aware training (QAT): the forward pass sees quantized weights while gradients update a high-precision copy. gpt-oss quantized its MoE weights to MXFP4 in post-training. DeepSeek-V4's MXFP4 expert weights dequantize losslessly to FP8 provided the largest and smallest 1×32 FP4 scales inside each 128×128 FP8 block differ by less than a set ratio, which DeepSeek checked empirically for its weights; its FP8 framework then runs unchanged. Kimi K3 runs MXFP4 expert-weight, MXFP8-activation QAT through all of post-training, and MiMo-V2.6 starts MXFP4 QAT in mid-training. The posttraining notes compares these schemes.

NVIDIA is the exception. It pretrained Nemotron 3 Super in NVFP4 for most linear layers over all 25T tokens, keeping the last 15% of the network, the attention projections and the embeddings in BF16; Nemotron 3 Ultra followed over 20T tokens. Underflow was the visible cost: by the end of Super's run, zero-valued weight gradients covered 7% of the parameters.

Who uses it and why

"Through the support for FP8 computation and storage, we achieve both accelerated training and reduced GPU memory usage."

"Due to potential risks of performance degradation that we observed during preliminary study, we do not apply FP8 in computation."

Trade-offs

  • Per-group scales need custom kernels: the extra FP32 additions slow the tensor cores unless two batches of work are overlapped, as DeepSeek does.
  • Sensitive layers stay in higher precision, so the end-to-end gain is below the GEMMs' theoretical 2×.
  • A wrong grouping can diverge, so each recipe needs long BF16 comparison runs.
  • Standard formats run on more hardware but can be less accurate: DeepSeek-V4.1-Flash kept MXFP4 for its indexer despite the higher accuracy of alternative formats in its tests.

Takeaways

  • Under one scale, a tensor's outliers push its small values into FP8's subnormals, so fine-grained FP8 recipes scale small groups separately and accumulate in FP32.
  • DeepSeek-V3's 1×128 tiles and 128×128 blocks made fine-grained scaling the pattern for large open models; the earlier MX standard builds the same idea into the format with 32-element blocks and power-of-two scales (MAI-Base-2).
  • DeepSeek, Meta, MiMo, MAI, NVIDIA, Ant, Qwen (3.5) and StepFun (Step 5) compute in FP8; Kimi K2 computes in BF16 and stores activations in FP8; FP4 arrives mainly through post-training QAT, except at NVIDIA, which pretrains Nemotron 3 Super and Ultra mostly in NVFP4.
Check yourself: why can DeepSeek-V3 use E4M3 for gradients when the FP8 paper recommends E5M2?

E5M2's extra exponent bit buys range that a single per-tensor scale needs. Each 1×128 tile has its own scale and spans a narrower range, so E4M3 suffices and its extra mantissa bit adds precision.

Check yourself: an MXFP8 (E4M3) block's largest magnitude is 3.0. What is its scale, and how many bits per element does it cost?

⌊log2 3.0⌋ − 8 = −7, so the scale is 2−7 and 3.0 maps to 384. Each element costs 8 bits plus 8 / 32 = 0.25 for the shared scale: 8.25 bits.

  1. Micikevicius et al., FP8 Formats for Deep Learning (2022), arXiv:2209.05433
  2. Rouhani et al., Microscaling Data Formats for Deep Learning (2023), arXiv:2310.10537
  3. Kalamkar et al., A Study of BFLOAT16 for Deep Learning Training (2019), arXiv:1905.12322
  4. DeepSeek-AI, DeepSeek-V3 Technical Report, §3.3 and App. B
  5. DeepSeek-V3.1 model card
  6. DeepSeek-V4 technical report, §5.2.1
  7. DeepSeek-V4.1-Flash technical report, §2.4.4
  8. Kimi Team, Kimi K2 technical report, §2.4
  9. Kimi Team, Kimi K3 technical report, §4.1.4 and §5.2.2
  10. Microsoft AI, MAI-Thinking-1 report, §2.6.3
  11. Microsoft AI, Frontier Pre-training at Microsoft AI (MAI-Base-2)
  12. Meta, The Llama 4 herd (launch blog)
  13. Xiaomi, MiMo-V2-Flash technical report, §2.1
  14. Xiaomi, MiMo-V2.6 technical report, §3.2
  15. OpenAI, gpt-oss-120b and gpt-oss-20b model card, §2.1
  16. NVIDIA, Nemotron-H report, Nemotron Nano 2 report, Nemotron 3 Super report, Nemotron 3 Ultra report and Nemotron 3 Nano Omni report
  17. Ant, Ling 2.0 report; Qwen, Qwen3.5 blog; StepFun, Inside Step 5 Preview

12 Data

Where do the 14 to 50 trillion training tokens of a large 2025-26 base model come from, and how do labs choose, clean, rewrite and check them?

How many tokens

How many tokens should a model of a given size see? A pretraining run reads a budget of D tokens. The Chinchilla study trained over 400 models and found that, for compute-optimal training, "the model size and the number of training tokens should be scaled equally". Chinchilla itself had 70B parameters and saw 1.4T tokens: 1.4×1012 / 7×1010 = 20 tokens per parameter. Compute-optimal counts training cost only; a smaller model also "reduces inference cost considerably".

Open models train far past that ratio:

  • Many tokens per parameter. Gemma 3 27B saw 14T tokens, about 520 per parameter or 26 times Chinchilla's ratio, and the dense MiMo-7B saw 25T, about 3,200 per parameter (its checkpoint holds 7.8B weights).
  • Growing budgets. 14.8T for DeepSeek-V3 (December 2024) and 15.5T for Kimi K2 (July 2025), then 27-50T in 2026, up to 50T for MAI-Base-2 (Figure 12.1).
  • Labs added in the atlas. Qwen3 was already at 36T in April 2025, MiniMax M2 used 29.2T in October 2025, and NVIDIA's Nemotron-H-56B and Ant's Ling 2.0 each used 20T; Qwen3.5 and 3.8, MiniMax M3, Step 5 and Mistral's models give no token count.

Labs count differently (MiMo includes later mixture stages), so small gaps mean little.

Pretraining tokens by release date 010T20T30T40T50T Jan 2025Jul 2025Jan 2026Jul 2026 PRETRAINING TOKENS DeepSeek-V3 14.8T Gemma 3 27B 14T Llama 4 Scout ~40T Maverick ~22T MiMo-7B 25T Kimi K2 15.5T GLM-4.5 22T MiMo-V2-Flash 27T GLM-5 27T DeepSeek-V4-Pro 33T MAI-Thinking-1 30T Inkling 45T GLM-5.3-Flash 30T corpus DeepSeek-V4.1-Flash 45T MiMo-V2.6-Pro 30T MiMo-V2.6-Flash 48T MAI-Base-2 50T
Figure 12.1. Pretraining tokens by release date, to scale (5 px per trillion), as each lab reports them. For GLM-5.3-Flash, Z.ai gives only the size of its 30T-token multimodal pretraining corpus (chapter 07), not the number of tokens trained.

What goes into the mix

Given a budget, how much of it should each kind of text get? A data mix gives each source family i (web, code, math, books) a share of the run, and the share decides how often that family's text is repeated:

Di = wishare · Drun's tokens,    ∑i wi = 1,    ei = Ditokens supplied / Uiunique tokens

Ui is what cleaning left of the family, so ei is how many times it is seen on average; ei above 1 means repetition. A 10T-token run that gives code w = 20% draws 2T code tokens; with 1T unique code tokens, each is seen e = 2 times.

Most labs describe the mix only in words. DeepSeek-V3 raised "the ratio of mathematical and programming samples", and Kimi K2 names four domains without shares. A few give numbers:

  • MiMo-7B raised math and code to about 70% in its second stage.
  • GLM-4.5 trained on 15T general tokens, then 7T of code and reasoning.
  • Ant raised Ling 2.0's reasoning share from 32% to 46% over its 20T tokens.
  • DeepSeek-V4.1-Flash mixes text-only and multimodal tokens 7:1.
  • NVIDIA publishes phase-by-phase mixes for its Nemotron models, and Microsoft AI (MAI) publishes full mixes for MAI-Base-1, the base of MAI-Thinking-1, and for MAI-Base-2 (Figure 12.2 and the worked example below).
MAI-Base-1 and MAI-Base-2 data mixes MAI-Base-1 (base of MAI-Thinking-1): 30T training tokens Code 16.4T Web 4.5T STEM 4.7T PDFs 1.4T Math 1.6T Books 0.9T Multilingual 0.5T MAI-Base-2: 50T training tokens Code 22.5T Web 6T PDFs 4.5T STEM 4.5T Vision-only 7T Books 2.5T Math 2T Other 1T 010T20T30T40T50T
Figure 12.2. Tokens per source family, to scale (16 px per trillion). Sources: MAI-Thinking-1 report Table 5; MAI-Base-2 report Figure 10 (shares × 50T).

Worked example: MAI-Base-1's 30T mix, family by family

Table 5 of the MAI-Thinking-1 report gives each family's share wi and unique tokens Ui for a D = 30T run. Multiply, then divide.

FamilywiDi = wi × 30TUiei
Code54.6%16.38 ≈ 16.4T7.4T16.4 / 7.4 = 2.22
STEM15.8%4.74 ≈ 4.7T2.2T2.17
Web text14.9%4.47 ≈ 4.5T8.1T0.55
Math5.4%1.62 ≈ 1.6T0.3T5.28
PDFs4.7%1.41 ≈ 1.4T2.7T0.53
Books and journals3.1%0.93 ≈ 0.9T0.6T1.65
Multilingual (other)1.6%0.48 ≈ 0.5T8.1T0.5 / 8.1 = 0.06
Total100%30.0T29.2T30.0 / 29.2 = 1.03

Small gaps from the report's ei (STEM: 4.7 / 2.2 = 2.14 vs 2.17) come from rounding Ui. Code is 7.4 / 29.2 = 25% of the unique tokens but 54.6% of training. Web and multilingual text are 16.2 / 29.2 ≈ 55% of the unique tokens but 16.5% of training. Math, the scarcest family, is repeated 5.28 times, near MAI's cap of 8 repetitions per dataset. The mix decides where repetition is spent.

Filtering and deduplication

How does a crawl of a trillion pages become a few billion training documents? Most of a web crawl never reaches training. MAI's pipeline shows the funnel:

  1. the crawl yields about 1.2 trillion pages;
  2. policy, adult-content and blocklist filters leave 794 billion;
  3. exact-duplicate removal leaves 423 billion;
  4. fuzzy deduplication leaves 73.4 billion English documents (plus 116.5 billion non-English ones);
  5. a quality classifier drops the bottom 70%, and heuristics leave about 4.6 billion, 6% of the deduplicated English set.

Rules can cut the wrong pages: MiMo found that rule-based filters "incorrectly filter high-quality web pages containing substantial mathematical and code content" and switched to small LLM taggers.

Deduplication matters because repetition drives memorization, and a page copied with small edits is still a repeat. Broder's resemblance measures the overlap: cut each document into w-word "shingles" (every run of w consecutive words) and compare the two shingle sets:

r(A, B) = |S(A) ∩ S(B)| / |S(A) ∪ S(B)|

A copy with one word changed still scores high. In a 1,000-word document with 7-word shingles, a changed word alters the 7 shingles that contain it: each version has 994 shingles, 987 are shared, and r = 987 / 1,001 = 0.986.

Comparing every pair of shingle sets is out of reach at this scale, so labs estimate r from short sketches. Under a random permutation of shingles, the smallest element of the union lands in the intersection with probability r, so short sketches of each document's smallest hashed shingles estimate r. MAI runs MinHash with locality-sensitive hashing (LSH) at a threshold of 0.8. LSH works on a signature of several MinHash values: it splits the signature into bands, hashes each band, and compares only documents that share a bucket in at least one band, which avoids comparing all pairs. GLM-4.5 found templated pages that MinHash missed and removed them by comparing document embeddings (SemDedup).

Shingles, sketches and resemblance in code
def shingles(doc, w=7):
    toks = doc.split()
    return {tuple(toks[i:i + w]) for i in range(len(toks) - w + 1)}

def sketch(doc, s=128):
    # a fixed 64-bit hash stands in for Broder's random permutation
    return set(sorted(hash64(sh) for sh in shingles(doc))[:s])   # MIN_s

def resemblance(m_a, m_b, s=128):
    union_min = set(sorted(m_a | m_b)[:s])          # MIN_s(M(A) ∪ M(B))
    return len(union_min & m_a & m_b) / len(union_min)

def dedup(docs, threshold=0.8):                     # MAI's fuzzy threshold
    kept = []                                       # (doc, sketch) pairs
    for d in docs:
        m = sketch(d)
        if all(resemblance(m, mk) < threshold for _, mk in kept):
            kept.append((d, m))
    return [d for d, _ in kept]   # all-pairs loop for clarity; MAI uses MinHash-LSH

Decontamination and knowledge cutoff

How do labs keep benchmark answers out of training? Decontamination removes benchmark items from the training data, so that a high score cannot come from memorized answers. The usual test drops any text that shares a run of n consecutive words with a test item. DeepSeek used 10-grams and removed about six million math texts; MAI uses 20-grams at 80% similarity. DeepSeek notes the method "cannot prevent the paraphrase of testset".

The knowledge cutoff is the last date of collected data, so benchmarks published later cannot leak in: V3's July 2024 cutoff predates CNMO 2024. Cutoffs trail releases by months: Gemma 3 (released March 2025) stops at August 2024, and MAI-Base-2 (October 2026) at March 2026. MAI-Base-1 lists one per source, from June 2025 for GitHub code to March 2026 for books.

Rephrasing and synthetic data

When high-quality text runs short, is it better to repeat it or to rewrite it? Kimi K2 rewrites: a language model paraphrases knowledge-heavy documents in varied styles, chunk by chunk, and a fidelity check compares each rewrite with its source. The method follows WRAP, which reported that rephrasing noisy web text "speeds up pre-training by ∼ 3×". On an early K2 checkpoint, rewriting beat repetition on SimpleQA:

Wiki text in trainingSimpleQA
raw text, repeated 10 times23.76
one rephrasing, repeated 10 times27.39
10 rephrasings, each seen once28.94

K3 reuses "the rephrasing recipe of Kimi K2". Other labs split on text written by models:

  • Generate it. MiMo-7B had reasoning models write analyses and solutions, data it found "can be trained for extremely high number of epochs without overfitting risk". Qwen3 had its own Qwen2.5 models synthesize trillions of tokens, and 3.53T of the 10.6T unique tokens behind Nemotron Nano 2 are synthetic.
  • Restrict it. MAI uses no model-generated data, and Mistral Small 3 used none. GLM-5 filters math and science data "to strictly avoid the use of synthetic, AI-generated, or template-based data". DeepSeek-V4.1-Flash drops low-information model outputs as "implicit duplication".

Distillation during pretraining

Can a teacher model give a richer target than the next word of the text? Next-token training uses a one-hot target: after "I drank a cup of", the text says "tea", and the loss rewards "tea" alone. A teacher might put 0.5 on "tea", 0.4 on "coffee" and 0.1 on "water", which also tells the student that coffee was nearly as likely. Knowledge distillation trains a student on such a predicted distribution. Hinton and colleagues note that high-entropy "soft targets" give "much more information per training case than hard targets". Gemma 2 used distillation to "simulate training beyond the number of available tokens".

Gemma 3 keeps only part of each teacher distribution. It samples 256 ids per position by teacher probability, zeroes the rest and renormalizes, which keeps 256 / 262,144 ≈ 1/1,000 of each distribution. Gemma 3 does not say why it samples. A plausible reason is cost: a full distribution over its 262k-entry vocabulary takes about 0.5 MB per token at 2 bytes per entry, for trillions of tokens. Sampling sometimes keeps low-probability tokens, which a top-k cut always drops; that dropped tail is the truncation bias Muse Glimmer addresses below. With teacher pT, student pS, context xc and sampled set S, the target q renormalizes the teacher over the sample and the loss is the cross-entropy to it:

q(x) = pT(x | xc) / ∑y∈S pT(y | xc) for x ∈ S,   0 otherwise;    ℒ = −∑x∈S q(x) log pS(x | xc)
The sampled distillation loss in code
def sampled_kd_loss(student_logits, teacher_logits, k=256):
    # logits: [n, V] for n token positions, vocabulary size V
    p_t = softmax(teacher_logits, axis=-1)              # [n, V]
    idx = sample_by_prob(p_t, k)                        # [n, k] ids, weighted by p_t
    rows = arange(p_t.shape[0])[:, None]                # [n, 1]
    q = zeros_like(p_t)                                 # [n, V]
    q[rows, idx] = p_t[rows, idx]                       # non-sampled entries stay 0
    q = q / q.sum(axis=-1, keepdims=True)               # renormalize over the sample
    log_p_s = log_softmax(student_logits, axis=-1)      # [n, V]
    return -(q * log_p_s).sum(axis=-1).mean()           # cross-entropy to sparse target
# the sparse target is k ids and k probabilities per token

Meta saves most teacher passes by distilling while the teacher trains. Llama 4 Maverick was "codistilled" from the nearly two-trillion-parameter Behemoth with a loss that "dynamically weights the soft and hard targets through training". Muse Glimmer uses the top 256 logits logged during Muse Spark's own pretraining. A KL-divergence loss, equal to cross-entropy up to a constant, runs for the first 95% of pretraining; plain cross-entropy on the true token runs for the last 5%, to address "the truncation bias inherent to top-k logit distillation". DeepSeek, Kimi, GLM and MiMo name no pretraining teacher, and MAI rules one out. NVIDIA's Nemotron 3.5 Lightning distills the top-128 logits of Nemotron 3 Super's base over 1T tokens into the existing Nemotron 3 Nano base, which these notes count as midtraining because it continues an earlier base.

Who uses it and why

"Specifically, a carefully designed rephrasing pipeline is employed to amplify the volume of high-quality tokens without inducing significant overfitting."

"Our pre-training is built on organic data which does not involve distillation from other models."

"Codistillation from Llama 4 Behemoth during pre-training amortizes the computational cost of resource-intensive forward passes needed to compute the targets for distillation"

Trade-offs

  • Repetition is cheap but raises memorization, so MAI caps repeats at 8 and deduplicates hard.
  • Rewritten text can drift from its source: Kimi names risks to "factual accuracy" and of "hallucinations and unintended toxicity", and MAI forgoes synthetic data for clean provenance.
  • Filters can delete wanted data (MiMo's math and code pages) or keep unwanted data (GLM-4.5's high-scoring templated pages).
  • N-gram decontamination misses paraphrased test items, and a later cutoff overlaps more published benchmarks.
  • Distillation needs teacher passes or logged logits; Gemma 3 found a smaller teacher better for short runs and a larger one for long runs, and Mistral found Small 3.1 a better teacher than the much stronger Medium 3 for its pruned Ministral 3 models.

Takeaways

  • Budgets rose from 14-40T tokens (2025) to 27-50T (2026), far past Chinchilla's 20 per parameter, so a mix is largely a choice of how often to repeat scarce high-quality text.
  • Kimi rephrases, MiMo generates reasoning text, and Qwen and NVIDIA generate trillions of tokens; MAI excludes model-generated text, GLM-5 filters it from math and science data, and DeepSeek-V4.1 drops low-information model output.
  • Gemma 3, Llama 4 Maverick and Muse Glimmer distill during pretraining, using 256 teacher entries per token or the teacher's own training passes.
Check yourself: MAI-Base-1 has about 0.3T unique math tokens and an 8-repeat cap. Could math have been 10% of its 30T run?

No. 10% of 30T is 3T, which is 3T / 0.3T = 10 passes. The cap allows 8 × 0.3T = 2.4T, or 8% of the run. More would need more unique math text or rewritten copies of it.

Check yourself: why does Muse Glimmer finish pretraining with 5% plain cross-entropy?

The target keeps only the teacher's top 256 tokens and gives every other token zero probability, which biases it. The true next token can be any vocabulary entry, so a final stretch on it addresses that bias.

  1. Hoffmann et al., Training Compute-Optimal Large Language Models (Chinchilla), arXiv 2203.15556
  2. Broder, On the resemblance and containment of documents (1997)
  3. Maini et al., Rephrasing the Web (WRAP), arXiv 2401.16380
  4. Hinton, Vinyals and Dean, Distilling the Knowledge in a Neural Network, arXiv 1503.02531
  5. Gemma Team, Gemma 2, arXiv 2408.00118
  6. Gemma Team, Gemma 3 Technical Report, arXiv 2503.19786 and Gemma 3 model card
  7. Microsoft AI, MAI-Thinking-1 / MAI-Base-1 report
  8. Microsoft AI, Frontier Pre-training at Microsoft AI (MAI-Base-2)
  9. Kimi Team, Kimi K2 technical report, arXiv 2507.20534
  10. GLM-4.5 technical report, arXiv 2508.06471 and GLM-5 technical report, arXiv 2602.15763
  11. MiMo-7B technical report, arXiv 2505.07608; MiMo-V2-Flash report; MiMo-V2.6 report
  12. DeepSeek-V3 technical report, arXiv 2412.19437; DeepSeek-R1, arXiv 2501.12948; DeepSeek-V4, arXiv 2606.19348; DeepSeek-V4.1 report
  13. Meta, The Llama 4 herd (blog) and Llama 4 Scout model card
  14. Meta, Muse Glimmer report
  15. Thinking Machines, Introducing Inkling; Z.ai, GLM-5.3-Flash blog
  16. Qwen, Qwen3 report; MiniMax, MiniMax-M2 series report; Ant, Ling 2.0 report; NVIDIA, Nemotron-H report, Nemotron Nano 2 base card, Nemotron 3 Nano report and Nemotron 3.5 Super and Lightning report; Mistral, Mistral Small 3 and Ministral 3 report

13 Putting it together: two model families

When a lab redesigns its model from one generation to the next, how do the separate choices in chapters 00 to 12 fit together?

Each earlier chapter took one design choice in isolation. Real redesigns change several at once, and the changes usually answer the same few pressures. This chapter walks through two model families in 2025 and 2026. Each walkthrough starts from one model's whole recipe, read in chapter order, then follows what each release changed. A sizing exercise that uses the calculator closes the chapter.

DeepSeek: from V3 to V4.1-Flash

The starting recipe. DeepSeek-V3 (December 2024) set the template many labs copied. In chapter order: a large mixture of experts, 671B total and 37B active, with auxiliary-loss-free balancing (chapters 01 and 02); MLA attention (03); 128K context through YaRN after pretraining (04); one multi-token-prediction module (06); AdamW (08); FP8 training with 1×128 tiles and 128×128 blocks (11); and 14.8T tokens (12). Over the next 21 months DeepSeek changed almost every part of it.

ChoiceV3 · Dec 2024V3.2-Exp · Sep 2025V4-Pro · Apr 2026V4.1-Flash · Sep 2026
Size671B total, 37B activesame 671B / 37B shape, continued from V3.1-Terminus1.6T total, 49B active552B backbone + 196B Engram memory; 16B active when generating
AttentionMLA, every layer fullMLA + sparse top-2,048 (DSA)compressed sparse (CSA) interleaved with heavily compressed attention (HCA)CSA2: KV and indexer keys shared across layers
Context128K, YaRN after pretraining128K1M, grown inside pretraining (4K → 1M)1M
Residual streamstandardstandardmHC, 4 streamssingle-pass mHC
OptimizerAdamW(inherited)Muon for most matriceshead-wise Muon for queries and keys
Draft modelMTP module(inherited)MTP moduleno MTP in pretraining; separate DSpark drafter
Modalitiestexttexttextimages from the start of pretraining
Pretraining tokens14.8T+0.95T of continued training33T45T

V3.2-Exp: one change on the same base. Read the attention row left to right and the logic of chapter 03 appears in order. V3's MLA shrank the cache. V3.2-Exp kept the cache but read only the 2,048 most relevant tokens per query, which cuts compute and memory traffic at long context. DeepSeek described it as an experiment:

"V3.2-Exp builds upon V3.1-Terminus by introducing DeepSeek Sparse Attention—a sparse attention mechanism designed to explore and validate optimizations for training and inference efficiency"

V4-Pro: a new base model. V4 grew to 1.6T total and 49B active parameters, adopted Muon for most matrices (chapter 08) and 4 mHC residual streams (chapter 05), and read 33T tokens. Its attention attacked memory itself by compressing the stored keys and values before selecting from them, and it moved to 1M context, grown inside pretraining. The payoff DeepSeek reports at 1M tokens is large: V4-Pro needs 27% of the per-token compute and 10% of the KV cache of V3.2, despite having more active parameters. V4 also carries the stability guards of chapter 10: RMSNorm on its queries and compressed KV entries in place of QK-Clip, and SwiGLU clamping and Anticipatory Routing against MoE outliers.

V4.1-Flash: a layout for agents. V4.1-Flash went further for a specific workload. Agents call tools constantly, and each tool result has to be processed (prefilled) before the model can continue:

"In agentic workflows, frequent tool calls generate extensive prefill requests, imposing severe computational overhead when KV caches miss."

Its answer was a causal encoder-decoder layout. The bottom half of the layers works as usual. The top half does not compute its global keys and values from its own hidden states; DeepSeek writes that they "are projected directly from the hidden state of the (L/2)-th layer" using a separate projection per layer. So when a long tool result arrives, its tokens only need to pass through the bottom half: the top half's keys and values for those tokens come from one cheap projection each. New tokens generated afterwards still run through all layers. This is why V4.1-Flash activates 8B parameters per token during prefill and 16B during decode. Two other terms in the table are new. CSA2 is V4.1's version of compressed sparse attention, in which groups of layers share one set of compressed keys and values and one indexer instead of each storing its own. Engram is a large table of embeddings that the model reads through hashing; DeepSeek describes it as adding "sparsely accessed conditional memory", meant to separate memorization from computation.

V4.1-Flash also takes images from the start of pretraining (chapter 07) and moves drafting out of pretraining into a separate DSpark drafter (chapter 06). The optimizer and residual-stream rows changed only with a new base model: V4 brought Muon and mHC in together, and V4.1 refined both.

Kimi: from K2 to K3

Moonshot's path shows a different habit: test a risky idea on a small research model first, then adopt it in a flagship.

The starting recipe. Kimi K2 (July 2025), in chapter order: 1.04T total and 32.6B active parameters, with 384 routed experts, 8 active and 1 shared, balanced by a bias without an auxiliary loss (01 and 02); MLA with 64 heads (03); 128K context with YaRN (04); MuonClip, Muon plus QK-Clip (08 and 10); a warmup-stable-decay schedule (09); BF16 compute with FP8 storage of selected activations (11); and 15.5T tokens, including rephrased knowledge text (12).

ChoiceK2 · Jul 2025Kimi Linear · Oct 2025K2.5 · Jan 2026K3 · Jul 2026
Size1.04T total, 32.6B active48B total, 3B active (research)K2 plus a 400M vision encoder2.78T total, 104.2B active
AttentionMLA, 64 heads3 KDA (linear) : 1 MLA, no RoPE in MLAMLA3 KDA : 1 gated MLA, no RoPE in MLA
Experts384 routed, 8 active, 1 shared256 routed, 8 active incl. 1 shared(inherited)896 routed, 16 active, 2 shared
Balancingbias, no auxiliary lossbias(inherited)quantile balancing
OptimizerMuonClipMuonClipMuonClipper-head Muon with clipping
Schedulewarmup-stable-decaywarmup-stable-decay(continued training)cosine
Residual streamstandardstandardstandardblock attention residuals
Modalitiestexttextvision added by continued trainingvision from the start
Context128K with YaRN1M256K1M, no RoPE changes

K2: fewer heads. K2's main architectural decision was to use half as many attention heads as DeepSeek-V3. The reason was the serving bill at long context:

"with a sequence length of 128k, increasing the number of attention heads from 64 to 128, while keeping the total expert count fixed at 384, leads to an 83% increase in inference FLOPs"

Kimi Linear: the hybrid, tested small. Kimi Linear tested the linear-attention hybrid from chapter 03 at 48B parameters, where a failed experiment is cheap. Moonshot reported that the hybrid "reduces memory and KV-cache usage by up to 75% during long-sequence generation while preserving global information flow via the full attention layers."

K3: the hybrid at flagship scale. Nine months later, K3 used the same 3:1 pattern at 2.78T parameters. K2.5 had added vision to K2 by continued training; K3 trains on images from the start. K3 also changed things that only matter at very large scale: quantile balancing because 896 experts are harder to keep evenly loaded, bounded activations (chapter 10) because unbounded SwiGLU outputs risked overflowing in low precision, and a cosine schedule because Moonshot's own scaling-law searches found it reached a lower loss than WSD. It also bounded KDA's decay rate (chapter 03) to a fixed range so that, in Moonshot's words, "both diagonal and off-diagonal tiles" of the chunked computation can "use dense Tensor Core matrix multiplications", which makes the linear layers faster on GPUs. From K2 it keeps the weight clipping and the rephrasing recipe.

Four pressures behind the changes

Almost every change in both walkthroughs answers one of four pressures. Figure 13.1 groups the choices from all chapters by the pressure they relieve: DeepSeek's attention changes fall under serving memory, and MuonClip and K3's bounded activations under stability.

Design choices grouped by the pressure they relieve Serving memory and bandwidthlong agent sessions Training efficiencymore model per FLOP Stability at scaleno spikes or divergence Data limitsrunning out of good text GQA, MLA (ch 03)sliding window + global (ch 03)sparse/compressed attention (ch 03)linear-attention hybrids (ch 03)fewer heads (Kimi K2)separate draft models (ch 06)over-training small models (ch 01)FP8 or FP4 KV cache (ch 11) mixture of experts (ch 02)more, smaller experts (ch 02)Muon (ch 08)FP8 and MXFP8 (ch 11)multi-token prediction (ch 06)fitted hyperparameter laws (ch 09)distillation in pretraining (ch 12) QK-norm, QK-Clip (ch 05, 10)mHC, attention residuals (ch 05)per-head Muon (ch 08)softcaps, z-loss, clipping (ch 10)bounded activations (Kimi K3)quantile balancing (ch 02)block-scaled low precision (ch 11) rephrasing (ch 12)synthetic reasoning data (ch 12)image, audio, video tokens (ch 07)filtering and dedup (ch 12)more epochs, capped per source
Figure 13.1. The same pressures explain most changes across labs. Several choices relieve more than one: MoE lowers both training and serving cost, and block-scaled FP8 is both an efficiency and a stability measure.

Two of these pressures grew sharply in 2025 and 2026. Serving cost grew because agents keep hundreds of thousands of tokens in context for many steps. Stability became harder because models crossed 1T and then nearly 3T parameters, and failures that were rare at smaller scale (exploding logits, overflowing activations, uneven expert loads) became common enough to need their own fixes.

Exercise: size a serving setup

You must serve 64 agent sessions at once, each with 256K tokens of context (262,144 tokens). After loading the weights, 300 GB of accelerator memory is left for the KV cache. Use the calculator (cache stored at 2 bytes per number) to decide which attention designs fit, and how many sessions each could hold.

Show the solution

The cache per session is (numbers stored per token) × 262,144 tokens × 2 bytes, plus any fixed state. From the model configurations:

  • GLM-4.5: 92 layers × 2 (key and value) × 8 KV heads × 128 = 188,416 numbers per token.
  • DeepSeek-V3: 61 layers × (512 latent + 64 rotary) = 35,136 per token.
  • DeepSeek-V3.2: 61 × (576 + 128 indexer key) = 42,944 per token.
  • gpt-oss-120b: 18 global layers × 2 × 8 × 64 = 18,432 per token, plus 18 sliding-window layers that never hold more than 128 tokens.
  • Kimi K3: 24 MLA layers × 576 = 13,824 per token, plus 69 KDA layers with a fixed state of 96 heads × 128 × 128 numbers each.
  • MiMo-V2-Flash: 9 global layers × 4 KV heads × (192 key + 128 value) = 11,520 per token, plus 39 sliding-window layers holding at most 128 tokens.
  • Kimi Linear: 7 MLA layers × 576 = 4,032 per token, plus 20 KDA layers with fixed states of 32 × 128 × 128.

Multiplying out and dividing 300 GB by the result gives the number of sessions that fit (the calculator above does the same arithmetic):

Model (attention design)Cache per sessionSessions in 300 GB
GLM-4.5 (GQA, full)98.8 GB3
DeepSeek-V3.2 (MLA + sparse)22.5 GB13
DeepSeek-V3 (MLA)18.4 GB16
gpt-oss-120b (1:1 window 128)9.7 GB31
Kimi K3 (3 KDA : 1 MLA)7.5 GB40
MiMo-V2-Flash (5:1 window 128)6.1 GB49
Kimi Linear (3 KDA : 1 MLA, small)2.1 GB140

Only the small linear-attention hybrid fits all 64 sessions. The rows compare attention designs at one length: GLM-4.5, gpt-oss-120b, DeepSeek-V3 and V3.2 were released for contexts of about 128K tokens, so their 256K figures show what the design would need, not a supported setting. Three lessons follow. First, sparse attention (DSA) does not save memory: V3.2 stores every token plus an index key, so its cache is larger than V3's; it saves compute and reads, which matter for speed. Second, the biggest memory savings come from not storing most tokens at all (sliding windows, linear-attention state) or from compressing what is stored (MLA, and V4's compression, which DeepSeek reports at 10% of V3.2's cache at 1M tokens). Third, storing the cache in FP8 instead of BF16 halves every cache size in the table and roughly doubles the session counts, so DeepSeek-V3 would fit 32 sessions. Each saving has a price: windows and linear layers lose exact access to distant tokens, which is why every window or linear design here keeps some full-attention layers.

Trade-offs

  • Changes that cut serving cost (compression, windows, linear layers) give up some exact recall of distant tokens; labs keep a fraction of full layers to compensate.
  • Training-side changes (optimizer, residual stream, numerics) usually wait for a new base model, so they arrive in bundles and are hard to evaluate one at a time.
  • Small research releases (Kimi Linear, DeepSeek V3.2-Exp) lower the risk of a change but delay it by one or two generations.

Takeaways

  • Most 2025-26 design changes answer four pressures: serving memory, training efficiency, stability at scale and limited data.
  • Attention changed most often because long agent sessions made the KV cache the main serving cost.
  • Labs often test a risky idea on a small or experimental release before adopting it in a flagship.
Check yourself: why is DeepSeek-V3.2's KV cache larger than V3's, if sparse attention is meant to make long context cheaper?

Sparse attention changes which tokens each query reads, not which tokens are stored. V3.2 still keeps the MLA latent for every token and adds a small index key per token for the lightning indexer. What it saves is the work and memory traffic of attending: each query reads 2,048 selected latents plus the cheap index keys instead of all latents.

Check yourself: Kimi tested linear attention on a 48B model in October 2025 but used it in a flagship only in July 2026. Why might a lab wait?

A new attention design changes the whole pretraining run, so a failure at flagship scale wastes months of compute. A small model shows whether quality holds and whether the kernels are fast enough at a fraction of the cost. Kimi also changed details before K3 (for example, bounding the decay so all tiles run on tensor cores), which needed the experience from the smaller model.

  1. DeepSeek-V3 technical report
  2. DeepSeek-V3.2-Exp report
  3. DeepSeek-V4 report
  4. DeepSeek-V4.1 report
  5. Kimi K2 report
  6. Kimi Linear report
  7. Kimi K2.5 report
  8. Kimi K3 report

A Glossary

Short definitions of the terms used in these notes, with the chapter that explains each one.

Acceptance length
In speculative decoding, the average number of tokens each pass of the large model yields: the accepted drafts plus the one token the large model adds. ch 06
Active parameters (Na)
The parameters a single token actually uses. In a mixture-of-experts model this is far smaller than the total. Training and inference compute scale with it. ch 01
All-to-all
A communication step in which every device sends data to every other device. Mixture-of-experts layers use it to send tokens to the devices that hold their experts and back. ch 02
Attention sink
A token or learned slot that absorbs attention a head does not want to spend elsewhere. Sliding-window models keep one so that dropping old tokens does not disturb the softmax. ch 03
Auxiliary-loss-free balancing
DeepSeek's way of spreading tokens evenly over experts: a per-expert bias is added to router scores only for choosing experts, and nudged up or down after each step depending on load. ch 02
BF16
A 16-bit floating-point format with the same exponent range as FP32 and fewer mantissa bits. The default input precision for matrix multiplies before FP8, with FP32 accumulation and an FP32 master copy of the weights. ch 11
Block diffusion drafter
A draft model that takes a block of masked future positions after one known token, lets them attend to each other in both directions, and fills the whole block in one forward pass (MiMo V2.6's DFlash drafts 7 tokens at once). ch 06
Block scaling
Storing a separate scale factor for each small block of a tensor (for example 128×128 weights or 32 values) so that low-precision numbers keep their accuracy. ch 11
Chinchilla-optimal
The split of a fixed training budget that minimizes loss: about 20 training tokens per parameter. Most 2025-26 models train on far more tokens than this to make serving cheaper. ch 01
Compressed sparse attention (CSA, HCA)
DeepSeek V4's attention: keys and values are compressed along the sequence before a sparse selection (CSA), interleaved with layers that attend densely to a much more heavily compressed sequence (HCA). ch 03
Cosine schedule
A learning-rate schedule that rises during warmup, then decays smoothly along a cosine curve to a small final value. ch 09
Decode and prefill
Prefill processes the whole prompt in parallel and is limited by compute. Decode generates one token at a time and is limited by how fast weights and the KV cache can be read from memory. ch 00
Decontamination
Removing training documents that overlap with evaluation benchmarks, so scores measure ability rather than memorized test items. ch 12
Delta rule
An update for linear-attention memory that first removes what the state already stores for a key, then writes the new value. It lets a fixed-size state overwrite old associations. ch 03
Distillation (knowledge distillation)
Training a student model to match a teacher's predicted distribution over tokens, not only the single correct next token. Gemma 3, Llama 4 Maverick and Muse Glimmer use it during pretraining. ch 12
Draft model and speculative decoding
A small model proposes several next tokens; the large model checks them all in one pass, keeps the drafts it accepts (by a rejection-sampling rule) and adds one token of its own. The output distribution is unchanged, but fewer slow passes are needed. ch 06
Dropless routing
Mixture-of-experts routing in which no token is dropped when many tokens pick the same expert; every token is processed by its chosen experts. ch 10
DSA (DeepSeek Sparse Attention)
A cheap "lightning indexer" scores every earlier token, and full attention then runs only on the top 2,048. ch 03
E8M0 scale
The shared scale in microscaling formats: an 8-bit number that stores only a power-of-two exponent, applied to a block of 32 values. ch 11
Encoder-free multimodal model
A model that turns image patches or audio frames into embeddings with a light projection and feeds them straight into the language model, with no separate vision or audio encoder. ch 07
Engram
A large embedding table that the model reads sparsely through hashing and adds to its hidden state through a context-dependent gate. DeepSeek V4.1-Flash uses 196B such parameters to separate memorization from computation. ch 13
Expert, router, top-k
In a mixture-of-experts layer, the feed-forward block is split into many experts. A router scores them for each token and only the top k run. ch 02
FP8 (E4M3, E5M2)
8-bit floating-point formats. E4M3 has more precision and is used for weights and activations; E5M2 has more range and is often used for gradients. ch 11
Gated MLA
MLA whose output is multiplied elementwise by a learned gate computed from the layer input. Kimi K3 uses it in its full-attention layers. ch 13
GQA, MQA
Grouped-query and multi-query attention: several query heads share one key/value head, shrinking the KV cache by the group size. ch 03
Hyper-connections, mHC
Widening the residual stream into several parallel streams that layers mix with learned weights. DeepSeek's manifold-constrained version (mHC) keeps the mixing matrix doubly stochastic so signals cannot blow up. ch 05
iRoPE
Llama 4's layer pattern: most layers use RoPE with local attention, and every few layers use global attention with no position encoding. ch 04
KDA (Kimi Delta Attention)
Moonshot's linear-attention layer: a gated delta rule with a per-channel decay. Interleaved about three-to-one with global attention layers in Kimi Linear, Kimi K3 (69 KDA to 24 MLA) and GLM-5.3-Flash. ch 03
KV cache
The keys and values of all earlier tokens, stored so each new token does not recompute them. Its size grows with context length and usually limits how many long sessions fit in memory. ch 00, ch 03
Ladder (scaling ladder)
A series of small models trained at increasing sizes with the same recipe, used to fit scaling laws and choose hyperparameters before the large run. ch 09
Linear attention
Attention rewritten so that each layer keeps a fixed-size state matrix instead of every past key and value, making per-token cost independent of context length. ch 03
LK loss
A training loss for draft models: the negative log of the expected acceptance rate, −log Σx min(p(x), q(x)), where p is the target's and q the drafter's distribution. ch 06
Logit softcap, z-loss
Two ways to keep logits from growing without bound: squash them with a scaled tanh, or add a small penalty on the squared log of the softmax normalizer. ch 10
Mamba-2
A state-space layer that, like linear attention, carries a fixed-size state from token to token instead of a growing cache. NVIDIA's Nemotron hybrids use it for most token mixing, with a few attention layers. ch 03
Mid-training
Training phases after the main pretraining run and before fine-tuning that change the data mix, context length or learning-rate schedule. See the midtraining notes. ch 12
MinHash and LSH
Tools for finding near-duplicate documents at scale: MinHash turns a document into a short signature whose agreement with another estimates their overlap, and locality-sensitive hashing (LSH) groups similar signatures so only likely duplicates are compared. ch 12
Mixture of experts (MoE)
A model whose feed-forward layers are made of many experts, of which each token uses only a few. Total parameters grow without growing the compute per token. ch 02
MLA (multi-head latent attention)
DeepSeek's attention that stores one compressed latent vector per token (plus a small rotary key) and reconstructs every head's keys and values from it. ch 03
MTP (multi-token prediction)
Training the model to also predict tokens further ahead. It adds training signal, and the extra head can be reused as a draft model. ch 06
Muon
An optimizer for weight matrices that applies momentum and then orthogonalizes the update with Newton–Schulz iterations, so every direction of the update moves by a similar amount. ch 08
MuonClip
Kimi K2's optimizer: Muon with weight decay and an update scale matched to AdamW, plus QK-Clip to keep attention logits bounded. ch 10
MXFP8
An 8-bit "microscaling" format in which each group of 32 values shares one power-of-two scale. ch 11
Newton–Schulz iteration
A short polynomial iteration that pushes all singular values of a matrix toward 1 without computing an SVD. Muon uses it to orthogonalize updates. ch 08
NoPE
No position encoding: a layer that uses no rotary or absolute position signal and relies on other layers or the causal mask for order. ch 04
NVFP4
NVIDIA's 4-bit floating-point format: E2M1 values with an FP8 scale per 16 elements and an FP32 scale per tensor. Nemotron 3 Super and Ultra were pretrained mostly in it. ch 11
On-policy distillation (OPD)
Distillation in which the student generates its own outputs and is trained to match the teacher's token probabilities on them. Used after pretraining; see the posttraining notes. ch 06
μP (maximal update parameterization)
Rules for scaling initialization and per-layer learning rates with model width so that hyperparameters tuned on a small model transfer to a large one. ch 09
Pipeline parallelism
Splitting a model's layers across devices in stages, with small batches flowing from stage to stage. ch 05
QAT (quantization-aware training)
Training with low-precision rounding simulated in the forward pass, so the weights still work well after they are stored in that precision. ch 11
QK-Clip
Kimi's fix for exploding attention logits under Muon: when a head's largest logit passes a threshold, its query and key weights are scaled down. ch 10
QK-norm, RMSNorm
RMSNorm rescales a vector by its root-mean-square. QK-norm applies it to queries and keys before the dot product, which keeps attention logits bounded. ch 05
RoPE, partial RoPE, p-RoPE
Rotary position embedding rotates pairs of query and key dimensions by angles that depend on position, so their dot product depends on position only through the offset between the two tokens. Partial variants rotate only some dimensions. ch 04
Shared expert
An expert that every token uses in addition to its routed experts, holding common knowledge so routed experts can specialize. ch 02
Sinkhorn normalization, doubly stochastic
A doubly stochastic matrix has nonnegative entries and every row and column summing to 1. Sinkhorn normalization reaches one by alternately rescaling rows and columns; mHC uses it to constrain its mixing matrix. ch 05
Sliding-window attention
Each token attends only to the last w tokens. Usually interleaved with some global layers that see the whole context. ch 03
Soft tokens
Continuous embedding vectors placed in the language model's input sequence, for example the 256 vectors Gemma 3 uses for one image, as opposed to discrete token ids. ch 07
Speculative drafters (EAGLE, DSpark, DFlash)
Small models trained to propose tokens for speculative decoding. EAGLE drafts from the target model's hidden states; DSpark is DeepSeek's separately trained drafter; DFlash drafts a block of tokens in parallel with a diffusion-style model. ch 06
Subnormal numbers
Floating-point values smaller than the smallest normal number, stored with fewer significant bits. They extend the range toward zero at reduced precision. ch 11
SwiGLU
The common feed-forward activation: the input goes through two projections, one passed through the SiLU (swish) function, their elementwise product goes through a third projection. ch 02
Tokens per parameter
Training tokens divided by (active) parameters. A simple measure of how far past compute-optimal a model was trained. ch 01
Training-time test
EAGLE-3's way of training a drafter: unroll it for several steps and feed it its own earlier predictions, as happens during inference. ch 06
WSD (warmup-stable-decay)
A schedule that holds the learning rate constant for most of training and decays it only at the end, so a run can be extended or branched before the decay. ch 09
WSM (warmup-stable-merge)
Ant's schedule for Ling: the learning rate stays constant to the end of training, and merging checkpoints takes the place of the decay. ch 09
YaRN
A method that rescales RoPE frequencies so a model trained at a short context can work at a longer one after brief extra training. ch 04

B Citation

To give credit if you find this work useful, please cite:

@misc{ma2026openrecipespretrain,
  title={Reading Open-Weight Recipes, Part 1: What 2025--26 Model Reports Disclose About Pretraining},
  author={Ma, Ziqiao},
  howpublished={\url{https://mars-tin.github.io/blogs/posts/open_recipes_pretraining}},
  note={Blog post},
  year={2026}
}