LLM Inference | For You
Lecture 8 of 9

MTP and Speculative Decoding

The main question of this lecture: remember the “impossible” \(2P/\beta\) ceiling from Lecture 1? How do we buy several accepted tokens for one read of the weights, and why is it not cheating?

The “Impossible” Ceiling, Revisited

We ended Lecture 1 with a hard floor. One decode step must read all \(P\) weights once, so a single-request step cannot take less than \[ T_{step} \ge \frac{2P}{\beta} \approx \frac{140\ \text{GB}}{3.35\ \text{TB/s}} \approx 41.8\ \text{ms} \] for a 70B model in FP16 on an H100. That is a ceiling of about 24 tok/s, at \(I \approx 1\) FLOP/byte, 300× below the ridge. Everything since (paging, batching, disaggregation, parallelism, kernel fusion) has lived above that line, trying to amortize the weight read across more requests or more work. None of it touched the wall itself.

TA says: and then production 2026 happened. Kimi K3 decoding on GB300, batch 1: 111–118 tok/s plain, which is already 86–92% of its (much lower, MoE) roofline, and 331–370 tok/s with speculation on. Remember the lever list from Lecture 1: shrink the bytes, buy more bandwidth, or produce several tokens per weight read. This lecture is the third lever. The wall was only ever a wall for sequential one-token-per-read decode. Today we walk straight through it, legally.

Main idea: Verification is free in a memory-bound decode: one read of the weights can score many candidate tokens in one parallel pass. So let something cheap draft \(k\) candidates, let the target model verify them all at once, accept the longest prefix that matches its own distribution, and roll the KV back over the rest. Every emitted token still comes from the target's distributions. That is why it is not cheating, and this lecture proves it.

Why Verification Is (Exactly) Free

Here is the one fact the whole module rests on. A forward pass over \(k\) tokens reads each weight matrix once and does \(k\) times the arithmetic: verification converts a GEMV into a GEMM with \(M = k\) rows for the same memory traffic. As long as the \(k\times\) extra compute fits inside the idle compute budget (recall that the compute utilization of single-request decode is \(\beta/\pi \approx 1/295 \approx 0.34\%\)), the step time does not move. Formally: \[ T_{verify}(k) = \max\!\Big( \underbrace{\frac{2P + B \cdot kv}{\beta \cdot MBU}}_{\text{memory: unchanged}},\; \underbrace{\frac{k \cdot 2P \cdot B}{\pi \cdot MFU}}_{\text{compute: grows linearly}} \Big) \quad\Longrightarrow\quad k \le \frac{\pi}{\beta}\cdot\frac{MFU}{MBU}\cdot\frac{2P + B \cdot kv}{2P\,B}. \] At \(B = 1\) and \(kv \cdot L \ll 2P\) (70B at \(L\) = 4K: the KV read is \(320\ \text{KB} \times 4096 \approx 1.3\) GB vs 140 GB of weights), the last factor is \(\approx 1\), and the ceiling collapses to \(k^* \approx \text{ridge} \times MFU/MBU\).

Worked example (do it with me): 70B on H100, \(B=1\), \(\pi = 990\) TFLOPS BF16, \(\beta = 3.35\) TB/s, \(2P = 1.4\times 10^{11}\) FLOPs/token.
  1. Decode-step time (memory-bound): \(140\ \text{GB} / 3.35\ \text{TB/s} = 41.8\) ms.
  2. Compute time for \(k\) tokens at a realistic \(MFU = 0.5\) for small GEMMs: \(k \cdot 1.4\times 10^{11} / (0.5 \times 9.9\times 10^{14}) = 0.283\,k\) ms.
  3. Ceiling: \(0.283\,k \le 41.8 \Rightarrow k^* \approx 148\).
Sweep it: \(k{=}1 \Rightarrow 0.28\) ms of compute (step ratio 1.00×); \(k{=}8 \Rightarrow 2.3\) ms (1.00×); \(k{=}64 \Rightarrow 18.1\) ms (1.00×); \(k{=}148 \Rightarrow 41.9\) ms, the break-even; \(k{=}300 \Rightarrow 84.9\) ms, now compute-bound and 2.03× slower. Under ideal \(MFU = MBU = 1\), \(k^* \approx 295\), exactly the ridge point; even at pessimistic \(MFU = 0.3\), \(k^* \approx 89\). Practical speculative decoding uses \(k \in [1, 16]\), one to two orders of magnitude below the ceiling. Verification is not approximately free at realistic \(k\); it is exactly free.
Engineering takeaway: the free-verification zone ends where the product \(B \cdot (k+1)\) approaches the ridge. The threshold is \(B \cdot (k+1) \gtrsim \pi\, MFU / (\beta\, MBU) \approx 150\text{–}300\) tokens per step. At \(k{+}1 = 5\), that is only \(B^* \approx 30\text{–}60\) concurrent requests, well inside production batch sizes. The same math that makes speculation free at \(B=1\) makes it expensive at serving scale. Sleep with that thought; we meet it again below.

The Framework: Draft → Verify → Accept

So: if verifying \(k\) tokens costs one decode step, can we find tokens worth verifying? Each speculative round goes:

  1. Draft. A cheap mechanism proposes \(k\) candidate continuations \(\hat{x}_{t+1}, \dots, \hat{x}_{t+k}\), as a chain or a candidate tree.
  2. Verify. One forward pass of the target model yields its next-token distributions at all \(k\) positions simultaneously, \(p(\cdot \mid x_{\le t}), p(\cdot \mid x_{\le t}, \hat{x}_{t+1}), \dots\) This is the same causal-mask trick as prefill, legal by the cache-legality induction of Lecture 1.
  3. Accept. Position by position, accept a candidate if it passes a test against the target distribution; truncate at the first failure. The verify pass at the failure position still yields the target's own distribution there, so every round emits at least 1 and at most \(k+1\) tokens. The “+1” is the bonus token computed for free by the same pass.
1. draft (cheap, serial) “the” “cat” “sat” “on” 2. verify: one pass, k rows, same bytes target model forward p(·) at all 5 positions at once (the prefill mask trick) 3. accept longest matching prefix “the” ✓ “cat” ✓ “sat” ✗ bonus ★ target says “the cat sleeps”: emit that instead, truncate the round roll back KV for the rejected tail (truncate + free blocks)
How to: follow one round left to right, top to bottom. Dashed boxes are guesses; green is what the target itself would have said; the amber bonus is why even a total rejection costs nothing in tokens: the verify pass always leaves one freshly computed target distribution behind.
? The draft is garbage and proposes four tokens the target hates. How many tokens does the round emit? Zero? Think for a minute before you open this; the answer is the key to why speculation can never make you slower in token count.

Possible answer

One. Always. Truncation happens at the first rejection, but the verify pass computed the target's own distribution at that position, so you emit the target's correct token there. A round commits \(r \in \{1, \dots, k{+}1\}\) tokens, never zero. The worst case is not lost work; it is the \(c_{draft}\) time you paid for the useless draft, plus a recoverable KV write.

The whole thing now rests on two questions: is the acceptance test exact, and how many tokens does a round yield on average? The next two sections answer them in order.

Not Cheating: Speculative Decoding Is Exact

This is the mathematical heart of the lecture, and the property that sets speculative decoding apart from every approximate acceleration (quantization, distillation, pruning): the output distribution is strictly identical to decoding with the target model alone. We prove it twice, because greedy and sampling need different tests.

Greedy: induction over rounds

Target greedy decoding is a deterministic function \(g(\text{prefix}) = \arg\max_x p(x \mid \text{prefix})\). A round drafts \(k\) tokens and the verify pass hands us \(g_i = g(\text{prefix}, \hat{x}_1, \dots, \hat{x}_{i-1})\) for all \(i = 1..k{+}1\) at once. The rule: accept \(\hat{x}_i\) iff \(\hat{x}_i = g_i\); stop at the first mismatch \(j\) and emit \(g_j\); if all \(k\) match, also emit the bonus \(g_{k+1}\).

Claim. The emitted sequence equals the target-greedy sequence exactly. Proof (sketch). Invariant: at the start of every round, the committed prefix equals the target-greedy prefix. Base: the shared prompt. Step: for every \(i < j\), the accepted \(\hat{x}_i\) equals \(g(\text{committed prefix}, \hat{x}_{<i})\), which by the invariant is the next greedy token; at position \(j\) we emit \(g_j\), the target's greedy token given the (now correct) prefix. Invariant restored, and \(1 \le r \le k{+}1\). ∎ Note the structural reason even total rejection is free: the verify forward wastes nothing.

Sampling: a rejection test that repairs the gap

Greedy comparison fails when we sample \(x \sim p\). The correct test, due to Leviathan, Kalman, and Matias, and independently Chen et al. (2023), is rejection sampling against the draft distribution. The draft drew \(x \sim q\); both \(p\) (from the verify pass) and \(q\) (from the draft) are known exactly:

Two one-line identities make it exact. Watch. First, the normalizer is the rejection probability: \[ Z = 1 - \sum_x \min(p(x), q(x)) = \tfrac{1}{2}\lVert p - q \rVert_1 = \Pr[\text{reject}], \] because \(\sum_x q(x)\min(1, p(x)/q(x)) = \sum_x \min(p(x), q(x))\), and \(\sum \max(0, p-q) = \sum p - \sum\min(p,q)\) pointwise (the two positive parts of \(p - q\) have equal mass, hence the \(\tfrac12\lVert p - q\rVert_1\) form). Second, the emitted token's law: \[ \Pr[\text{final} = x] = \underbrace{q(x)\min\!\big(1,\; p(x)/q(x)\big)}_{\text{accepted draft}} + \underbrace{Z\,\tilde{p}(x)}_{\text{rejection} \times \text{residual}} = \min(p, q) + \max(0, p - q) = p(x). \]

Worked example (one position, three tokens, real numbers): \(p = (0.5, 0.3, 0.2)\), \(q = (0.4, 0.4, 0.2)\).
  1. Per-token acceptance \(\min(1, p/q)\): tokens 1..3 get \((1.0,\ 0.75,\ 1.0)\).
  2. Overall acceptance: \(\sum_x q(x)\min(1, p(x)/q(x)) = 0.4 + 0.3 + 0.2 = 0.9\), so \(Z = 0.1 = \tfrac12(0.1 + 0.1 + 0) = \tfrac12\lVert p - q\rVert_1\). ✓
  3. Residual: \(\max(0, p - q) = (0.1, 0, 0)\), so \(\tilde{p} = (1, 0, 0)\).
  4. Final law: token 1: \(0.4 \cdot 1 + 0.1 \cdot 1 = 0.5\); token 2: \(0.4 \cdot 0.75 + 0 = 0.3\); token 3: \(0.2\). Exactly \(p\).
Read the story, not just the arithmetic: the draft overproposes token 2 (0.4 vs 0.3), so we reject it 25% of the time; it underproposes token 1, and residual resampling repairs exactly that deficit.

Sanity checks (the two limits). If \(q = p\): acceptance is 1 everywhere, \(Z = 0\), never reject: pure speedup. If \(q\) and \(p\) have disjoint support: acceptance is 0 everywhere, \(Z = 1\), the residual \(\tilde{p} = p\), and every round degenerates to sampling from the target directly. Still correct, just no gain. The scheme interpolates between “free tokens” and “ordinary decode” as a function of draft quality \(\tfrac12\lVert p - q\rVert_1\). Lifting one position to whole sequences is an induction over committed positions: the invariant (the committed prefix has exactly the target's law) makes the chain-rule product telescope to the target's sequence distribution.

Note: temperature and top-\(p\) compose cleanly: apply the warper to both \(p\) and \(q\) before the test, and the identical algebra goes through.
Engineering takeaway: losslessness is a theorem about distributions, not floating-point bit-exactness: the verify forward runs at a different GEMM \(M\) than plain decode, so kernels may differ in the last ulp (Lecture-7 deterministic-kernel discipline if you need reproducibility). And the acceptance test costs one comparison per position, so never skip it “because acceptance is high”: an untested draft silently changes the output distribution.

The Speedup Law: τ Over (1 + cdraft)

Exactness settled. Now, how fast is it? Model acceptance as i.i.d. per position with probability \(\alpha\) (a first-order approximation; real acceptance correlates through the prefix, and we will honour that later). A round with \(k\) draft positions accepts a geometric run up to the first rejection, plus the bonus token: \[ \tau = \sum_{i=0}^{k} \alpha^i = \frac{1 - \alpha^{k+1}}{1 - \alpha} \quad \xrightarrow[k \to \infty]{} \quad \frac{1}{1 - \alpha}. \] The asymptote is the field's fundamental tension: for \(\alpha = 0.85\) it caps at 6.67, and no chain length escapes it. Raising \(k\) buys less and less, while (for autoregressive drafters) costing more and more.

Per round, time is \(T_{tgt} \cdot (1 + c_{draft})\): the target step plus the draft cost in units of a target step, verification free inside the ceiling. Tokens per round: \(\tau\). Baseline: \(\tau\) tokens cost \(\tau\,T_{tgt}\). Hence the course's canonical formula: \[ \text{speedup} \approx \frac{\tau}{1 + c_{draft}}, \] with exactly two levers that organize everything that follows: raise \(\tau\) (draft quality and alignment) and lower \(c_{draft}\) (draft efficiency, especially its scaling in \(k\)).

Worked example (three tables an engineer reads daily): τ(k; α) from the geometric sum:
\(\alpha\)k=1k=2k=3k=4k=6k=8k→∞
0.701.7002.1902.5332.7733.0593.1993.33
0.851.8502.5733.1873.7094.5295.1236.67
0.951.9502.8533.7104.5246.0337.39520.0
Check one cell yourself: MTP at \(\alpha = 0.85,\ k = 1\) gives \(\tau = 1 + 0.85 = 1.85\) ✓, matching DeepSeek-V3's reported 85–90% second-token acceptance, i.e. \(\tau \in [1.85, 1.90]\).

Optimal \(k\) under an autoregressive draft, \(c_{draft} = k\,c_1\), maximizing \(\tau(k)/(1 + k c_1)\) numerically over \(k \in [1, 40]\):
\(\alpha\)\(c_1 = 0.02\)\(c_1 = 0.05\)\(c_1 = 0.10\)
0.70k* = 8, 2.76×k* = 6, 2.35×k* = 4, 1.98×
0.85k* = 14, 4.75×k* = 10, 3.70×k* = 7, 2.85×
0.95k* = 31, 9.95×k* = 21, 6.60×k* = 15, 4.48×
Two readings: (i) the optimum is an interior point, because \(\tau\)'s concave growth eventually loses to \(c_{draft}\)'s linear growth; (ii) it shifts right as acceptance improves and left as the draft gets expensive. This is why DeepSeek's production choice \(k = 1\) for MTP is rational (per-step draft cost is not negligible and acceptance is already high), while EAGLE deployments tune \(k \approx 4\text{–}8\).

Parallel draft (DFlash-style), \(c_{draft} \approx 0.15\) independent of \(k\):
\(\alpha\)k=4k=8k=12k=16
0.853.22×4.45×5.10×5.43×
0.953.93×6.43×8.46×10.12×
With seriality removed, the speedup keeps climbing with block length toward the \(\tau\)-asymptote \(\div 1.15\). The ceiling on \(\tau\) itself becomes the binding constraint.
draft length k → tokens per round / speedup → 0 2 4 6 1 4 8 12 16 asymptote 1/(1−α) = 6.67, no chain escapes it τ(k), α = 0.85 τ / (1 + 0.05k) k* ≈ 10, 3.70×
How to: pick \(k\) on the x-axis and read both curves. Green is how many tokens a round yields: concave, doomed to saturate. Blue is the actual speedup once the draft costs \(0.05k\) per round: it peaks at an interior point and declines. The amber marker is the whole design problem: k* lives between the two shapes, and it moves with \(\alpha\), \(c_1\), and (as we will see) the current batch size.

Draft Trees: Spend the Budget Where Uncertainty Is

A chain has a concrete flaw: it commits the draft budget to one guess per position. But language is not equally predictable everywhere. When the target distribution is peaked, one candidate suffices; when it is spread over a few plausible continuations, no single one is likely to match. A tree draft keeps several candidates per position and lets verification pick the longest passing branch.

committed prefix “the” “quick” “fast” “a” “brown” “quick” accepted path rejected branches (grey, dashed) tree attention mask: “fast” attends to {prefix, “the”}, NOT to “quick” or “a” every node attends only to its ancestors, so its p(·) has exactly the autoregressive conditioning: Lecture-1 legality again one pass verifies the whole tree
How to: the root is the last committed token; each level is one position of the future; every node gets its own target distribution in one verify pass under a tree-shaped causal mask. The longest green path commits; dashed grey branches existed only to be scored, then are discarded.

The math generalizes the chain: writing \(a(v)\) for the acceptance probability of node \(v\) given its parent is accepted, at most one node per level can continue the committed sequence, so the level events are disjoint and \[ \mathbb{E}[\tau_{tree}] - 1 = \sum_{v \ne root} \prod_{u \in path(root, v)} a(u) \xrightarrow{\text{i.i.d. } \alpha} \sum_{v \ne root} \alpha^{\,\text{depth}(v)}. \] Note the honesty constraint: sibling acceptance events are (nearly) disjoint, so children of a node sum to \(\lesssim 1\). A branching node helps only to the extent its children partition probability mass. Trees pay precisely when the distribution is entropic.

Worked example (same budget of 4 draft tokens, two architectures): Chain at \(\alpha = 0.55\): \(\mathbb{E} = \sum_{i=1}^{4} 0.55^i = 1.11\). Tree with two children at depth 1 covering 0.9 of the mass (\(\gamma_1 = 0.9\)) and one child each at depth 2 with \(\gamma_2 = 0.55\): \(\mathbb{E} = \gamma_1 + \gamma_1\gamma_2 = 0.9 + 0.495 = 1.40\). The tree wins, because depth-1 uncertainty was the bottleneck. On a peaked distribution the same budget in a chain wins; it depends on where entropy sits.

And the cost side argues back. A tree of \(n\) nodes is verified in one forward over \(n{+}1\) tokens, so the ceiling binds when \(B \cdot (n{+}1) \approx 150\text{–}300\) tokens per step. At \(B = 32\) that is a budget of 5–9 tokens per request: a chain of \(k \le 4\text{–}8\), or only a small tree. Production systems choose chain vs small tree as a function of current load, and EAGLE-2's confidence-based dynamic trees (expand branches exactly where the draft itself is uncertain) are as much a load-management feature as an accuracy feature.

Four Generations of Drafts: the Road to Alignment

The speedup law said \(\tau\) and \(c_{draft}\) are everything; the field's history is a four-generation push on both axes at once. Walk it the way the flaws dictate.

Gen 1: an independent small model (a 1B of the same family drafts for 70B). The easiest thing you can do... and you probably can guess the flaws: a second model to train and deploy, \(k\) serial autoregressive draft steps, and a softmax geometry never aligned with the target's. Poor \(\tau\), real \(c_{draft}\). Largely obsolete.

Gen 2: Medusa deletes the second model: \(k\) lightweight heads sit on the target's last hidden state, head \(i\) predicting token \(t{+}i\). Extremely cheap. But now the flaw is coordination: all heads condition on the same hidden state and predict independently, so the joint plausibility of the \(k\)-gram suffers. Alignment, not speed, is the bottleneck.

Gen 3: EAGLE fixes the conditioning: a single small transformer layer runs autoregressively over the target's features: (last-layer hidden state, embedding of last token) in, next feature out, the target's own LM head on top. The move from token-level to feature-level autoregression is the single biggest alignment jump: the hidden state is a sufficient statistic of the prefix; a sampled token is a lossy projection of it. One small-layer step per candidate, dynamic trees (EAGLE-2), multi-layer feature fusion (EAGLE-3). This is the widely deployed baseline in vLLM and SGLang.

Gen 4: MTP (DeepSeek-V3) asks: why should the draft be learned outside the default?

DFlash: deleting the draft's for-loop

Every draft so far is autoregressive: \(k\) candidates cost \(k\) sequential draft forwards, so \(c_{draft}\) grows linearly in \(k\) and caps how far \(\tau\) can be pushed (the interior optima above). DFlash attacks the seriality itself: the draft is a lightweight block-diffusion model that processes one anchor token plus several mask tokens and fills in the whole block of typically 8–16 candidates in parallel, the way masked-diffusion LMs denoise a block at once. Conditioning on the target's multi-layer features keeps alignment high; outputs are projected through the target's LM head, as in EAGLE/MTP. Reported (DFlash paper, ICML 2026): lossless speedups of 6× or more across models and tasks, up to 2.5× over EAGLE-3; NVIDIA's Blackwell evaluation reports up to 15× throughput at equal interactivity on gpt-oss-120b vs EAGLE-3; integrations in SGLang, vLLM, TensorRT-LLM; official draft checkpoints for mainstream open-model families; a UCSD team completed a TPU implementation.

Important: losslessness survives untouched. The diffusion parallelization is confined to proposing candidates; any shortfall in draft quality only lowers \(\alpha\), and verify/accept backstops correctness exactly as before. Parallel drafting trades acceptance probability for draft latency; it can never trade correctness. With \(c_{draft}\) decoupled from \(k\), the block length becomes a free variable and the ceiling reverts to the \(\tau\)-asymptote \(1/(1-\alpha)\), now attacked through alignment rather than draft latency. That is the precise sense in which DFlash “opens up the ceiling of \(\tau\)”.

TA says: the 2026 canonical deployment is DSpark, Kimi K3's production drafter. It is the DFlash recipe made MLA-native: it conditions on the target's compressed MLA latent rather than full per-head K/V, so the drafter never materializes the cache the architecture was designed to eliminate. Measured on GB300 at batch 1: 111 → 331 tok/s at TP8 (2.98×), 118 → 370 tok/s at TP16 (3.14×); SGLang reports 113 → 423 tok/s (3.74×). Run our consistency checks. (1) Against the Lecture-1 floor: K3 activates ≈26 GB of weights per step, so \(2P/\beta \approx 7.8\) ms, a ≈129 tok/s ceiling. Plain decode at 111–118 tok/s is already 86–92% of roofline, so speculation was the only remaining lever. (2) Against the speedup law: reading it backwards, \(\tau = 4.73\) with a realized 3.14× implies \(c_{draft} \approx \tau/\text{speedup} - 1 \approx 0.51\). So one diffusion pass plus round overhead costs about half a target step, exactly the DFlash prediction. (3) Against the \(\tau\) model: accepted tokens per round are 4.73 on coding workloads vs 2.61 on creative ones. Solving \((1-\alpha^{k+1})/(1-\alpha) = 4.73\): at \(k = 4\), \(\alpha \approx 0.97\); at \(k = 8\), \(\alpha \approx 0.83\); in the large-block limit \(\alpha \to 1 - 1/\tau \approx 0.79\) (creative: \(0.62\text{–}0.67\)). So the implied per-position acceptance moves ≈ 0.17 between task mixes (it is not a property of the drafter!), and inside a diffusion block later candidates condition on drafted, not committed, tokens. The i.i.d. formula is a calibration device, not a mechanism model. Report \(\tau\) and \(c_{draft}\) both, or report neither.

Engineering takeaway: choose the draft source by where your bottleneck sits in \(\tau/(1 + c_{draft})\). Checkpoint ships MTP weights (DeepSeek-V3 family)? Enable it; the decision is made. No built-in speculation? EAGLE-3 is the mature baseline. Single-stream latency dominates and you can host a block-diffusion drafter? DFlash is the frontier. The obsolete option, self-hosting an independent small model, survives only as the teaching example.

Speculation Meets the Rest of the System

Speculative decoding is not a kernel you bolt on; it changes the shape of decode (rounds commit a random \(r \in \{1, \dots, k{+}1\}\) tokens), and every layer of Lectures 2–7 feels it. Walk the stack with me.

Batching: the gain inverts with load

Free verification presumes spare compute, and spare compute is a small-batch luxury. Small batch: \(I \approx 1\), 300× under the ridge, speculation pays up to the full \(\tau/(1+c_{draft})\). Large batch: verify multiplies tokens per step by \(k{+}1\), and once \(B(k{+}1) \gtrsim 150\text{–}300\), decode crosses the ridge and goes compute-bound. The extra verify FLOPs crowd out paying work they would otherwise have served \(k\times\) over. Break-even batch (70B on H100, \(L\) = 4K, \(MFU = 0.5\), \(MBU = 1\)):

\(k\)1248
\(B^*\) (verify becomes compute-bound)≈ 253≈ 93≈ 41≈ 19

Production consequence: engines continuously estimate batch size and realized acceptance, and adjust \(k\), or switch speculation off entirely when loaded. A static \(k\) is a bug under drifting load. And one more hygiene rule: an acceptance number without a task distribution is uninterpretable. DSpark's \(\tau\) moved from 4.73 to 2.61 between coding and creative traffic.

KV management: reserve for the worst case, roll back the rest

Streaming: ITL becomes bimodal

A worked micro-example on our running 70B (MTP, \(k = 1\), \(\alpha = 0.85\), \(c_{draft} = 0.10\)): a round takes \(41.8 \times 1.1 = 46.0\) ms and emits 1 token with probability 0.15 or 2 tokens with probability 0.85. Per-token inter-arrival times are bimodal: ≈ 46 ms within a round, ≈ 0 ms for the second token of a 2-token round. Meanwhile the mean ITL drops to \(46.0/1.85 = 24.9\) ms from 41.8 ms. Remember Lecture 1: TPOT is a mean, ITL is a distribution. Mean-only monitoring misreads speculative systems twice: it hides the bursts from users watching the stream, and the per-round granularity from capacity planners.

CUDA graphs and EP: multipliers everywhere

CUDA graphs: the draft forward (\(M = B\)) and the verify forward (\(M = B(k{+}1)\), plus tree-mask variety) have different shapes, each needing its own captured buckets. The forward inventory doubles, and a variable \(k\) multiplies it again. Practical systems capture a small fixed set of \(k\) values, or run the (small) draft eagerly and capture only verify. Expert parallelism: per-step all-to-all volume scales with tokens in the step, so \[ V^{spec}_{a2a} = (k{+}1)\cdot V^{plain}_{a2a}. \] For DeepSeek-V3 (top-8 of 256 routed experts, \(d_{model} = 7168\)): ≈ 57 KB FP8 dispatch plus ≈ 115 KB BF16 combine ≈ 172 KB per token, and MTP at \(k = 1\) doubles it. This lands on links 3.7–67× narrower than HBM (900 GB/s NVLink down to 50 GB/s IB, vs \(\beta = 3.35\) TB/s). DeepSeek's production \(k = 1\) is exactly this three-way trade: high acceptance, minimal verify compute, only 2× communication, instead of chasing \(\tau\)-gains paid in all-to-all volume. (Larger expert batches partly self-correct GEMM efficiency; the network does not.)

Engineering takeaway: budget speculation end-to-end, not per component. Compute three numbers at your operating point: (i) \(B(k{+}1)\) vs the ≈ 150–300 tokens/step ridge budget (compute); (ii) \((k{+}1)\times\) the Lecture-6 all-to-all volume vs link bandwidth (EP); (iii) \((k{+}1) \times kv\) reservation vs free blocks (KV). The binding constraint is whichever you are closest to. It moves with load, so re-evaluate continuously.

Rollback without a KV: speculation on linear attention

Everything above assumed per-token KV: rejected positions own identifiable entries, and rollback is truncation. The 2026 hybrid models break that assumption structurally. Kimi K3's 69 KDA layers carry a rolling recurrent state \(S \in \mathbb{R}^{128 \times 128}\) per head: 3.0 MiB BF16 per layer, ≈ 0.2 GiB per request across all KDA layers, fixed regardless of context length. It is updated in place by the gated delta rule: \[ S_t = (I - \beta\, k k^\top)\, \mathrm{Diag}(\alpha)\, S_{t-1} + \beta\, k v^\top. \] There is no per-token entry to free: processing \(k\) draft tokens overwrites the committed state, diffusing the draft's contribution into every element of \(S\). Rejecting a suffix requires a state rewind, not a pointer truncation. It is the same logical requirement as KV rollback, with different mechanics and a different cost model.

Note (notation collision, inherited from the Kimi Linear paper): in the delta rule, \(\alpha\) is a per-channel decay gate, \(\beta\) a write strength, \(k, v\) the key/value vectors. These collide with this course's \(\alpha\) = acceptance rate, \(\beta\) = HBM bandwidth, \(k\) = draft length. Context disambiguates; the equation above is KDA-internal.

The 2026 solution space:

Engineering takeaway: on hybrid linear-attention models, budget rollback in state bytes and replay time, not KV blocks: snapshot cost is (KDA state per request) × (snapshot frequency), about 0.2 GiB per snapshot for K3, and replay cost is one recurrent pass over the accepted window. An engine that treats recurrent state like paged KV (truncate-and-free) is silently wrong; one that snapshots per round without compressing the draft window pays the full state size as a per-round tax.

Common Pitfalls

Watch out:
  1. Reporting \(\tau\) without a task distribution. Code/math vs open-ended dialogue can differ by multiples. Name the task mix, temperature, and draft configuration.
  2. Leaving speculation on at large batch. Past \(B(k{+}1) \approx\) the ridge budget, verify compute displaces paying work; the “speedup” becomes a throughput loss. You need a load-aware kill switch, not just an on flag.
  3. Forgetting KV rollback. Truncate rejected KV and release the blocks. Output stays correct if you forget; the leak is silent, and capacity accounting drifts.
  4. Static \(k\) under drifting load. The optimum moves with \(\alpha\), \(c_{draft}\), and \(B\); fix \(k\) at an offline optimum and you are mis-tuned most of the day.
  5. Believing “lossless” means bit-identical logits. Losslessness is distributional; GEMM-shape nondeterminism can perturb the last ulp. Pair with deterministic kernels if reproducibility is a hard requirement.
  6. Counting the draft as free. \(c_{draft}\) includes extra kernel launches and host round-trips; measured values are routinely 2–3× the FLOP estimate. Profile before you project.

Research Thinking

How to: read the starting point; read the question and think, for a minute, a day, a week... and only then open the answers. You are not supposed to reinvent several months of someone's research; each of these was someone's paper. It's the habit of thinking that counts: you have ideas, you try; if they don't work, you think again.

? Card 1, why this test? Starting point: the rule \(\min(1, p(x)/q(x))\) plus residual \(\tilde{p} \propto \max(0, p-q)\) is provably exact. Question: could we save a resample with a simpler rule: accept the draft token whenever the target likes it at least as much as the draft did (\(p(x) \ge q(x)\)), reject otherwise? Compute what distribution that rule emits on \(p = (0.5, 0.3, 0.2)\), \(q = (0.4, 0.4, 0.2)\). Think first.

Possible answer

Existing solutions: this is exactly the Leviathan–Kalman–Matias / Chen et al. (2023) construction. The two independent original speculative-decoding papers both arrived at rejection sampling, because exactness is forced, not found.

? Card 2, “invent” dynamic tree drafting. Starting point: a chain wastes its budget when entropy concentrates at one level (chain 1.11 vs tree 1.40 for the same 4 draft tokens); a fat tree wastes it back on peaked distributions; and \(B \cdot (n{+}1)\) must fit the ≈ 150–300 token/step ridge budget. Question: what signal, available online and for free from the draft itself, should decide where (and whether) to branch?

Possible answers

Existing attempts: EAGLE-2's confidence-based dynamic trees do the first; production deployments switching chain ↔ small tree on batch telemetry do the second; and on hybrid linear models, TreeWY removes the per-branch snapshot cost that made trees painful there. The combination of the two signals is, as of 2026, still an active design space.

? Card 3, design the dynamic-\(k\) controller. Starting point: \(k^*\) is an interior point of \(\tau(k)/(1 + c_{draft}(k))\), shifting with \(\alpha\) (workload), \(c_1\) (draft), and \(B\) (load, via the ridge budget: \(B^* \approx 41\) at \(k=4\) on our 70B example). A static \(k\) is a bug under drifting load. Question: sketch the control loop: what do you measure, what do you recompute, how often, and where is the kill switch? Which signal saturates first as \(B\) grows?

Possible answer

Existing attempts: this is the production behavior the literature describes. Engines adjust \(k\) from real-time acceptance and batch telemetry or disable speculation when loaded; DeepSeek's fixed \(k = 1\) is the conservative limit of the same policy at very high acceptance. Your Lab 8 curve (speedup peaking at small \(B\) and crossing 1.0 where the intensity argument predicts) is the measurement version of this card.

? Card 4, roll back what you cannot truncate. Starting point: paged KV admits rollback by truncation; a rolling recurrent state \(S_t = (I - \beta kk^\top)\,\mathrm{Diag}(\alpha)\,S_{t-1} + \beta kv^\top\) admits none, because the draft's contribution diffuses into every element of \(S\). Question: enumerate the logically possible rollback mechanisms for such a state, price each in state bytes and replay time, and say what makes tree drafting specially painful here.

Possible answers

Existing attempts, all 2026: SGLang ReplaySSM (snapshot+replay with the 32× window compression), TreeWY (snapshot-free tree verification for GDN-family linear layers), vLLM EAGLE3-on-KimiLinear (engine-owned hybrid draft/verify state), GLM-5.3-Flash's 1-MTP-layer checkpoint unfolded to MTP-5. Keep the lecture point: on hybrids, rollback is budgeted in state bytes × frequency, and an engine that treats recurrent state like paged KV is silently wrong.

Have Fun! Be the Verifier

Enough theory. Now you run some rounds. Set an acceptance probability \(\alpha\), a draft length \(k\), and a draft cost \(c_1\) per token, watch the theoretical numbers, then press the button to simulate real rounds: green bars are accepted draft tokens, the amber ★ is the bonus, red ✗ are the aborted tail. Can you make the empirical speedup beat theory? (It happens; small samples are generous.)




Playground physics: τ is the geometric sum \(\sum_{i=0}^{k}\alpha^i\); the round simulator samples the geometric run honestly, redundancy and all.

Seminar & Homework

Take Lab 8: Speculative Decoding from the hands-on pack. One GPU, three server configs: baseline (no speculation), prompt-lookup n-gram (--speculative-config '{"method":"ngram","num_speculative_tokens":5,"prompt_lookup_max":4}'), and an EAGLE head (--speculative-config '{"model":"<eagle-head-repo>","num_speculative_tokens":5}'; SGLang equivalent: --speculative-algorithm EAGLE --speculative-draft-model-path ... --speculative-num-steps 5 --speculative-eagle-topk 4 --speculative-num-draft-tokens 8). Two datasets: code completion (near-deterministic boilerplate) and open-domain chat; fix ignore_eos, 256 outputs, seed 0.

Lab pitfalls to self-audit: benchmarking on unpredictable prompts and crediting the engine; comparing spec-on vs spec-off across engines and calling it an engine comparison; ignoring the draft model's VRAM (it eats cache capacity); and reporting a \(B = 1\) speedup as a serving result. In the seminar, present your τ-table next to the theory table and defend one dynamic-\(k\) rule on your own telemetry.

Summary

← Lecture 7: The Kernel Level Lecture 9: Frameworks and New Workloads →