AnyLearn
All lessons
AIadvanced

Speculative decoding: making LLM inference faster without changing the output

How draft-then-verify decoding gets multiple tokens per forward pass of a large model, why rejection sampling makes it provably lossless, and where the draft comes from (small models, Medusa heads, self-speculation, EAGLE trees).

Not signed in: your progress and quiz score won't be saved.
Progress1 / 12

The autoregressive bottleneck

A transformer generates text one token at a time: to produce token t it must have already produced t-1. Each token is a full forward pass over billions of parameters, and at batch size 1 that pass is memory-bandwidth bound, the GPU spends most of its time streaming weights from memory, not doing math. So the arithmetic units sit mostly idle, and end-to-end latency scales almost linearly with the number of tokens.

The key observation: verifying a proposed sequence is cheap in a way that generating it is not. If you already had a candidate continuation, one forward pass could score every position in it at once, using the idle compute the sequential loop wastes. Speculative decoding is built entirely on turning generation into verification.

Full lesson text

All 12 steps on one page, for reading, reference, and search.

Show

1. The autoregressive bottleneck

A transformer generates text one token at a time: to produce token t it must have already produced t-1. Each token is a full forward pass over billions of parameters, and at batch size 1 that pass is memory-bandwidth bound, the GPU spends most of its time streaming weights from memory, not doing math. So the arithmetic units sit mostly idle, and end-to-end latency scales almost linearly with the number of tokens.

The key observation: verifying a proposed sequence is cheap in a way that generating it is not. If you already had a candidate continuation, one forward pass could score every position in it at once, using the idle compute the sequential loop wastes. Speculative decoding is built entirely on turning generation into verification.

2. The core idea: draft, then verify

Speculative decoding runs two models. A small, fast draft model q guesses the next few tokens cheaply, autoregressively. Then the large target model p, the one whose output you actually want, checks all of those guesses in one parallel forward pass.

Because the target scores γ\gamma drafted positions plus one more in a single pass, a good run yields several tokens for the price of one target step. A bad run (the draft guessed wrong early) falls back to roughly one token, the same as ordinary decoding. So the technique never makes you slower in expectation; it only ever adds tokens-per-pass when the draft is right.

The whole game is: make the draft cheap, make it agree with the target often, and verify in a way that doesn't change what the target would have produced on its own.

3. One speculative step

The draft proposes; the target verifies in parallel; a rejection corrects losslessly.

flowchart TD
A["Draft model q proposes gamma tokens (cheap, autoregressive)"] --> B["Target model p scores all gamma+1 positions in ONE parallel pass"]
B --> C["Walk the draft left to right, accept each token with prob min(1, p over q)"]
C --> D["First rejection at position j?"]
D --> E["Yes: keep the accepted prefix, resample token j from norm(max(0, p minus q))"]
D --> F["No rejection: accept all gamma, sample one bonus token from p"]
E --> G["Append accepted tokens, continue from the new context"]
F --> G

4. Verification that changes nothing: rejection sampling

The magic is the acceptance rule. Walk the draft left to right. For a drafted token x, accept it with probability

α=min ⁣(1,p(x)q(x))\alpha = \min\!\left(1, \frac{p(x)}{q(x)}\right)

where p(x)p(x) and q(x)q(x) are the target and draft probabilities for that token in that context. If the target likes the token at least as much as the draft did (pqp \ge q), accept outright. If it likes it less, accept only proportionally.

On the first rejection, discard the rest of the draft and resample that one position from the corrected residual distribution, the normalized positive part of pqp - q:

xnorm(max(0,  pq))x \sim \operatorname{norm}\big(\max(0,\; p - q)\big)

Stern, Leviathan, and Chen proved this makes the whole scheme lossless: the tokens you emit are distributed exactly as if you had sampled from the target p alone. Greedy decoding matches token-for-token; sampling matches in distribution.

5. Why it is faster

One target forward pass now yields more than one token whenever the draft's leading guesses survive verification. If each drafted token is accepted independently with rate α\alpha and you draft γ\gamma tokens per step, the expected number of tokens emitted per target pass is

E[tokens/pass]=1αγ+11α\mathbb{E}[\text{tokens/pass}] = \frac{1 - \alpha^{\gamma+1}}{1 - \alpha}

At α=0.8\alpha = 0.8 and γ=4\gamma = 4, that is about 3.4 tokens per target pass instead of 1, a large latency win.

Crucially, the win comes from the memory-bandwidth slack of the batch-1 regime. The extra drafted positions ride along in the same weight-streaming pass, so verifying 5 positions costs barely more than verifying 1. The gains are real but bounded by two things: how often the draft agrees with the target (α\alpha), and how cheap the draft is relative to the target.

6. The speculative step in pseudocode

The loop makes the accept/reject rule concrete. Note the single parallel target_p(...) call over all drafted positions, and the break on first rejection:

# one speculative step: draft with q, verify with target p
draft = []
for _ in range(gamma):                 # draft gamma tokens (cheap, sequential)
    draft.append(sample(q(context + draft)))

p = target_p(context + draft)          # ONE parallel pass -> [gamma+1, vocab]

out = []
for j, tok in enumerate(draft):
    if uniform(0, 1) < min(1, p[j][tok] / q[j][tok]):
        out.append(tok)                # accept
    else:                              # reject: resample the residual, then stop
        out.append(sample(normalize(relu(p[j] - q[j]))))
        break
else:
    out.append(sample(p[gamma]))       # all accepted -> free bonus token

That for/else is doing real work: the else runs only when the loop finished with no break, i.e. every drafted token was accepted, so you also collect the target's bonus token.

7. Choosing the draft length

How many tokens should the draft propose per step? The parameter γ\gamma is a tradeoff, not a free dial.

  • Larger γ\gamma raises the ceiling on tokens-per-pass, but acceptance is compounding, so the marginal token is accepted only with probability αk\alpha^k, which decays fast. Beyond a point you are mostly paying draft cost for tokens that get rejected.
  • Smaller γ\gamma wastes less draft compute per rejection but caps your best-case speedup.

The sweet spot depends on the acceptance rate: a well-aligned draft (α\alpha near 0.9) rewards a longer γ\gamma; a weak draft wants a short one. Many systems make γ\gamma adaptive, shortening it when recent acceptance drops. The draft is pure overhead on any step where the first token is rejected, so a draft that is both cheap and frequently right matters more than a long one.

8. Where the draft comes from, part 1: a separate small model

The original recipe (Leviathan et al.; Chen et al.) uses a separate small language model as qq, say a 1B model drafting for a 70B target. It is simple and modular: swap the draft freely.

Two practical constraints:

  • Shared vocabulary. Acceptance compares p(x)p(x) and q(x)q(x) token-for-token, so the draft and target must tokenize identically. A draft with a different tokenizer needs remapping and loses alignment.
  • Alignment beats raw quality. What matters is that qq agrees with pp where pp is confident, not that qq is good in absolute terms. Distilling the draft from the target's own outputs raises the acceptance rate more than simply using a stronger off-the-shelf small model.

The cost is operational: you now serve and keep two models resident in memory.

9. Where the draft comes from, part 2: draft with the target itself

Serving a second model is annoying, so a family of methods draws the draft from the target, no separate network to deploy:

ApproachHow it draftsTrade-off
MedusaExtra lightweight heads on the target predict several future positions from its last hidden stateNo second model; heads are trained, add params
Self-speculative (Draft & Verify)Run a subnetwork of the target (skip some attention/MLP layers) as the draftZero extra parameters; lower acceptance
Prompt / n-gram lookupDraft by copying likely continuations from the prompt or an n-gram tableFree; only wins on repetitive, quotation-heavy text

Each trades a bit of acceptance rate for operational simplicity. Medusa and self-speculation keep everything inside one served model; lookup drafting adds essentially no compute at all and shines when the output echoes the input (code edits, summarization with quotes).

10. Trees, not chains: tree attention and EAGLE

A linear draft is one bet: a single chain of γ\gamma tokens. If token 2 is wrong, tokens 3 onward are wasted. Tree drafting hedges by proposing several candidate continuations arranged as a tree, then verifying all branches in one pass using a masked tree attention pattern (each node attends only to its ancestors). More of the tree survives, so more tokens are accepted per step.

The EAGLE line pushes this hard. Instead of predicting tokens, it autoregresses at the feature level and conditions the draft on the target's own deeper hidden states, which makes its guesses agree with the target far more often. Combined with draft trees, EAGLE-2 and EAGLE-3 report acceptance rates high enough for roughly 3-4x lossless speedups. The pattern generalizes: richer, better-aligned draft structures buy more accepted tokens per verification, at the cost of a bit more verify-time compute.

11. What it buys you, and what it does not

Speculative decoding is one of the few free lunches in inference, but the lunch has a shape.

  • Lossless, genuinely. With correct rejection sampling the output distribution is identical to the target's. This is not quantization or distillation; quality does not move.
  • A latency win, not always a throughput win. The speedup comes from spare compute in the memory-bandwidth-bound, low-batch regime. At high batch size the target pass is already compute-bound, so the extra drafted positions compete for the same busy units and the gain shrinks, sometimes to nothing.
  • It depends on agreement. Off-distribution inputs, high sampling temperature, or a poorly aligned draft drop α\alpha, and with it the benefit.
  • It adds moving parts. A draft model or extra heads, more memory, and verification logic in the serving stack.

So it is a latency accelerator for interactive, low-batch serving, not a universal throughput multiplier.

12. The durable mental model

Strip away the specific methods and one idea remains: turn expensive sequential generation into cheap parallel verification, and correct the guesses in a way that changes nothing. Everything else, a separate draft model, Medusa heads, layer-skipping, EAGLE's feature trees, is just a different way to produce guesses that the target will accept often.

That framing is why speculative decoding became standard plumbing: modern serving engines (vLLM, TensorRT-LLM, SGLang, TGI) ship it, and new draft methods slot into the same accept-and-correct backbone without touching the correctness proof. When you evaluate a new variant, ask the two questions the math forces: how cheap is the draft and how often does the target accept it. Those two numbers, not the branding, determine the speedup.

Check your understanding

The lesson ends with a 5-question quiz. Take it in the player above to see your score.

  1. What inefficiency does speculative decoding exploit to speed up single-request LLM inference?
    • At low batch size the target's forward pass is memory-bandwidth bound, leaving compute idle that can verify several drafted tokens in one pass
    • It permanently compresses the target model's weights so each forward pass is cheaper
    • It lowers the numerical precision of the target model during generation
    • It skips generating low-probability tokens entirely to shorten the output
  2. A drafted token has target probability p(x) and draft probability q(x). With what probability is it accepted?
    • p(x) * q(x)
    • 1 - q(x)
    • min(1, p(x) / q(x))
    • min(1, q(x) / p(x))
  3. When a drafted token is rejected, what makes the overall scheme lossless (identical in distribution to sampling from the target)?
    • The whole draft is discarded and generation restarts from scratch with the target
    • The rejected position is resampled from the normalized positive part of (p - q)
    • The rejected token is replaced by the target's single most likely token
    • The draft model is retrained on the spot to match the target
  4. What problem do Medusa heads and self-speculative (layer-skipping) decoding primarily solve?
    • They make the output higher quality than plain decoding from the target
    • They remove the need for the parallel verification pass
    • They eliminate the shared-vocabulary requirement between draft and target
    • They draft using the target model itself, avoiding the need to serve a second separate draft model
  5. A team sees a big speedup from speculative decoding at batch size 1 but almost none once they batch many requests together. Why?
    • Rejection sampling stops being lossless at high batch sizes
    • The acceptance rate is mathematically forced to zero when batching
    • At high batch size the target pass becomes compute-bound, so the extra drafted positions compete for already-busy compute instead of using idle capacity
    • Draft models cannot run at all inside a batched server

Related lessons

AI
advanced

Loop engineering: verification, orchestration, and anti-patterns

Make loops trustworthy. Adversarial verification panels, sub-agent orchestration, loop-until-dry for unbounded discovery, loop-until-budget for paid depth, multi-modal sweeps with diverse prompts, eval-driven cap selection, and the five anti-patterns — silent caps, infinite plans, drift, premature termination, thrashing — that ship to prod more than they should.

9 steps·~14 min
AI
intermediate

Loop engineering in production: state, errors, and budgets

Once an agent loop runs past a few iterations the failure surface shifts: state bloats, tool calls fail in three distinct ways, retries multiply if you stack them wrong, and unbounded budgets rack up four-figure bills overnight. The state, errors, and budgets you need to make the loop survive contact with reality.

8 steps·~12 min
AI
beginner

Loop engineering basics: the agent control loop

How LLM agents actually run: the iterative prompt-action-observation loop, the ReAct shape, the smallest tool-calling loop in twelve lines, why you always stack three termination layers, what the model sees on iteration N, and when a single prompt is the better answer.

8 steps·~12 min
AI
intermediate

LLM Observability with OpenTelemetry: GenAI Semantic Conventions

Master the OTel GenAI semantic conventions — gen_ai.* attributes, span structure for prompts/completions/tools, sampling strategies, and cost attribution — and understand why standardizing across LangSmith, Phoenix, Datadog, and Grafana matters for production AI systems.

13 steps·~20 min