Back to Blog
Machine Learning

Speculative Decoding: One Equation & Four Levers

VESSL AI
VESSL AI
||11 min read
Speculative Decoding: One Equation & Four Levers

Why are GPUs mostly idle during decode?

Autoregressive generation emits one token per forward pass:

xip(x<i),i=1,2,,Nx_i \sim p(\,\cdot \mid x_{<i}), \qquad i = 1, 2, \dots, N

Generating NN tokens takes NN sequential passes. The memory dependency is the problem, not the arithmetic.

Consider one decode step on a 70B model in bf16. It reads about 140 GB of weights from HBM to produce a single token. On an H100 at 3.35 TB/s, that is roughly 42 ms, about 24 tok/s. The arithmetic in that same pass is around 2P=1.4×10112P = 1.4 \times 10^{11} FLOPs against a 989 TFLOP/s peak. In other words, that single decode step that uses 42 ms of memory traffic only utiltizes 0.14 ms of compute.

Because decode is memory-bound by two to three orders of magnitude, the GPU cores remain mostly idle for the entirety of the decode phase.

Roofline: where decode, speculation and prefill sit relative to the memory and compute roofs
Roofline: where decode, speculation and prefill sit relative to the memory and compute roofs

In the graph above, you can see that up to a certain point, verifying γ\gamma tokens in one pass multiplies arithmetic intensity by roughly γ\gamma while leaving weight traffic unchanged. However, at the ridge point (marked by the dotted line), memory and compute become equally binding. Before the ridge point, while the weights are already in transit, any speculative positions stacked on top of that load are essentially free.

Most acceleration techniques make each step cheaper: Quantization and sparsity cut bytes per weight, larger batches amortize weight traffic, and Better kernels shave constants. These techniques leave the serialization intact, and can only shrink the cost of a single step.

Speculative decoding, however, shrinks the overall number of steps. It attacks the sequential dependency itself, and it is the only acceleration technique that can be made exactly lossless.

The algorithm for speculative decoding

Take a look at the pseudocode below: A cheap drafter proposes γ\gamma tokens. One target forward pass over γ+1\gamma+1 positions checks all of them in order for the position of the first rejection, and eliminates any drafted tokens after. The longest unbroken run of drafted tokens is kept, and the first rejection point is replaced with a freshly resampled token, and the cycle begins again. The commit is a prefix (not an arbitrary subset) because correctness is based off of a token-by-token basis, in the order the drafter generates them.

# one speculative cycle
#   prefix x[:i], speculation length gamma
#   M_t = target, M_d = drafter

# --- draft phase: gamma sequential cheap steps ---
for j in range(gamma):
    q[i+j]  = M_d(prefix=x[:i] + draft[:j])
    draft[j] = sample(q[i+j])

# --- verify phase: ONE target pass over gamma+1 positions ---
p[i : i+gamma+1] = M_t(x[:i] + draft, causal_mask=True)

r = uniform(0, 1, size=gamma)
n = first_index_where(r > p[i+j][draft[j]] / q[i+j][draft[j]])   # or gamma

emit(draft[:n])                                   # n accepted tokens
if n < gamma:
    emit(sample(normalize(relu(p[i+n] - q[i+n]))))  # corrected token
else:
    emit(sample(p[i+gamma]))                        # free bonus token

truncate_kv_cache(to=len_emitted)

Two things to notice. The γ\gamma ratio tests happen in parallel after one target pass, so verification has no sequential dependency, which is the entire point. And a rejection still emits one corrected token, so τ1\tau \geq 1: speculation never stalls.

The ideas behind this come from branch prediction in CPUs, but there are two differences between CPUs and LLMs that matter in practice, and limit the applications of speculative decoding:

  1. A CPU misprediction is a correctness event; an LLM rejection is a statistical one. In CPU branch prediction, there is one true answer, since the branch condition evaluates to true or false. However, in speculative decoding, a drafted token can be perfectly reasonable text and still get rejected, because the test is based on distributional probability, not binary correctness.
  2. In a CPU, discarding mispredicted work, or a pipeline flush, is cheap and easily handled by the hardware. LLM rollback is cheap only because the KV cache is append-only, a premise that breaks for architectures that don't work this way, like recurrent-state and linear-attention models.

In other words, the benefits of speculative decoding aren't universal across all sequence architectures, as its benefits are enabled by how ordinary transformer KV caches are structured.

The acceptance rule

The proof that speculative decoding is exactly lossless.

Draw xqx \sim q from the drafter. Accept with probability min ⁣(1,p(x)q(x))\min\!\big(1, \tfrac{p(x)}{q(x)}\big). On rejection, sample the replacement from the normalized residual:

p(x)=max(0,  p(x)q(x))uVmax(0,  p(u)q(u))p'(x) = \frac{\max\big(0,\; p(x) - q(x)\big)}{\sum_{u \in \mathcal{V}} \max\big(0,\; p(u) - q(u)\big)}

The intuition: qq gives too much mass to some tokens and too little to others. The ratio test removes the excess. The residual is exactly the deficit, renormalized.

Theorem (losslessness). The emitted token is distributed exactly as pp.

Proof. Let β=umin(p(u),q(u))\beta = \sum_u \min(p(u), q(u)). The acceptance path contributes q(x)min ⁣(1,p(x)q(x))=min(p(x),q(x))q(x)\min\!\big(1, \tfrac{p(x)}{q(x)}\big) = \min(p(x), q(x)). The rejection path contributes (1β)p(x)(1-\beta)\,p'(x), and since the normalizer equals 1β1 - \beta, that is exactly max(0,p(x)q(x))\max(0, p(x) - q(x)). Summing:

min(p(x),q(x))+max(0,p(x)q(x))=p(x)\min\big(p(x), q(x)\big) + \max\big(0,\, p(x) - q(x)\big) = p(x)

The proof uses no property of qq at all. That single fact opens the whole design space: n-gram tables, suffix automata, diffusion models, quantized networks, the target with half its layers skipped. All legal, all lossless, no change to the correctness argument.

So every improvement to the drafter is purely an efficiency improvement. Inside the lossless branch there is no quality trade-off.

And the acceptance rate has a closed form:

α  =  Exq ⁣[min ⁣(1,p(x)q(x))]  =  uVmin(p(u),q(u))  =  1DTV(p,q)\alpha \;=\; \mathbb{E}_{x \sim q}\!\left[\min\!\left(1, \frac{p(x)}{q(x)}\right)\right] \;=\; \sum_{u \in \mathcal{V}} \min\big(p(u), q(u)\big) \;=\; 1 - D_{TV}(p, q)

This identity is from Leviathan et al. (2023). It turns a systems question (how often does the fast path fire?) into a statistics question: how close are two distributions in L1L_1. That is what makes drafter training a well-posed optimization with a known optimal objective, and it is why the rest of this post can be arithmetic rather than intuition.

Two corollaries people get wrong. Top-1 agreement is not α\alpha, except at temperature 0. And α\alpha is per-position: any single number you have been quoted is an average over an unstated mix of contexts.

What determines the speedup | one equation

Assume acceptance is i.i.d. Bernoulli(α)\text{Bernoulli}(\alpha), and let c=Tdraft/(γTtarget)c = T_{\text{draft}} / (\gamma \, T_{\text{target}}) be the drafter's relative cost. Expected tokens per cycle is a truncated geometric:

E[τ]=k=0γαk=1αγ+11α\mathbb{E}[\tau] = \sum_{k=0}^{\gamma} \alpha^k = \frac{1 - \alpha^{\gamma+1}}{1 - \alpha}

A cycle costs (cγ+1)Ttarget(c\gamma + 1)\,T_{\text{target}}. Dividing gives the speedup equation, also from Leviathan et al. (2023):

  S(γ)  =  E[τ]cγ+1  =  1αγ+1(1α)(cγ+1)  \boxed{\;S(\gamma) \;=\; \frac{\mathbb{E}[\tau]}{c\gamma + 1} \;=\; \frac{1 - \alpha^{\gamma+1}}{(1 - \alpha)\,(c\gamma + 1)}\;}

Three parameters: α\alpha, cc, γ\gamma. Almost every speculative decoding paper published since 2018 intervenes on one of four terms:

Lever What it does Examples
α\alpha \uparrow make the drafter's qq closer to the target's pp, so drafts are accepted more often EAGLE, DistillSpec, MTP
cc \downarrow cut the cost of drafting relative to the target FR-Spec, MagicDec, parallel drafters
γ\gamma realloc. spend the same draft budget on a different shape, a tree instead of a chain SpecInfer, Sequoia, EAGLE-2
rule change relax the accept test itself, giving up the lossless guarantee typical acceptance, Judge, SpecTr

In words: the first lever makes the drafter more accurate, since α=1DTV(p,q)\alpha = 1 - D_{TV}(p, q) and every step qq takes toward pp raises the acceptance rate. The second makes drafting cheaper relative to the target, so each cycle carries less overhead at the same α\alpha. The third keeps the budget fixed and changes its shape, drafting a tree of candidates instead of a single chain; a later section covers it. The fourth changes the accept test itself, at the price of the lossless guarantee.

Three mathematical constraints to keep in mind:

1. There is a hard ceiling, and cc sets it.

S    min{1c,  11α}S \;\le\; \min\left\{\frac{1}{c},\; \frac{1}{1-\alpha}\right\}

No amount of drafter accuracy rescues a drafter that is not cheap.

2. Speedup is not automatic. At γ=1\gamma = 1, S=(1+α)/(c+1)S = (1+\alpha)/(c+1). Speculation loses unless α>c\alpha > c. A drafter half as expensive as the target has to be right more than half the time.

3. α\alpha and cc are coupled. The optimal γ\gamma rises with α\alpha and falls with cc, so you cannot tune them separately.

Speedup against speculation length for several acceptance rates
Speedup against speculation length for several acceptance rates

The peak shifts right as α\alpha grows. It is also flat: at α=0.8\alpha = 0.8, every γ\gamma from 6 to 11 is within 3% of optimal. Getting α\alpha and cc right matters far more than getting γ\gamma exactly right, which is why adaptive-γ\gamma schedulers earn their keep by staying out of the region where γ\gamma is far too large, not by locating γ\gamma^\star precisely.

Setting S/γ=0\partial S / \partial \gamma = 0 gives the stationarity condition

αγ+1(c(cγ+1)lnα)=c\alpha^{\gamma+1}\big(c - (c\gamma + 1)\ln \alpha\big) = c

whose left side is strictly decreasing in γ\gamma, so SS is unimodal. Good news for any scheduler that searches γ\gamma greedily.

Best achievable speedup over the acceptance-rate / draft-cost plane, with iso-speedup contours
Best achievable speedup over the acceptance-rate / draft-cost plane, with iso-speedup contours

The graph above makes the ceiling concrete. Movement along the α\alpha axis buys much less than movement down the cc axis, and below the α=c\alpha = c line no amount of γ\gamma helps at all.

How far off the ceiling you actually land is worth internalizing. At c=0.05c = 0.05 the bound is 1/c=201/c = 20, but α=0.95\alpha = 0.95 tops out at 6.66.6 (at γ21\gamma^\star \approx 21), and α=0.8\alpha = 0.8 at 3.13.1. The ceiling is a bound, not a target.

Reallocating γ\gamma: trees instead of chains

One lever deserves a note before we move on. Reallocating γ\gamma means replacing the scalar with a structure: instead of one chain of γ\gamma tokens, draft a tree of candidate continuations and verify many chains in a single target pass, under a mask that keeps each branch causal with respect to its own ancestors. The budget is unchanged; only the shape of the spend is.

Choosing that shape has a clean answer. Value each node by its survival probability ava_v, the chance it is reached and accepted, and take the global top-nn. Because ava_v can only decrease along a root path, that greedy choice is automatically prefix-closed, and it is optimal at fixed budget. The same argument reappears over three different index sets (tree nodes, draft positions within a block, whole requests in a batch), which is why one proposition ends up covering tree construction, draft-length selection, and batch scheduling alike.

Why speculation spends more compute | the second theorem

S(γ)S(\gamma) is a wall-clock statement. It assumes the extra verified tokens are free, which holds only in the memory-bound regime.

Leviathan et al. states a second theorem in the same paper, this one counting arithmetic operations rather than wall-clock time. With c^\hat{c} the drafter's operations ratio, the expected increase in total arithmetic is:

(1α)(γc^+γ+1)1αγ+1  >  1\frac{(1 - \alpha)(\gamma\hat{c} + \gamma + 1)}{1 - \alpha^{\gamma+1}} \;>\; 1

Speculative decoding costs more compute than it saves. It converts compute into latency.

So if you are optimizing time-to-token at fixed load, S(γ)S(\gamma) is your number and speculation is a win. If you are optimizing tokens per second at saturation, the equation above is your number and speculation is a cost. Both readings are correct. A benchmark that reports only one of them has not told you whether to deploy it.

This shows up in production. DeepSeek's hardware retrospective describes MTP as slightly hurting throughput while significantly improving end-to-end latency. That is the operations-count theorem, observed at scale.

What VESSL AI measured

VESSL AI serves several open-source models, including GLM-5.2 and MiniMax-M3, in production on VESSL Cloud with speculative decoding, and the number that comes back depends less on the drafter than on where it is measured.

Here is one system, Solar-Open2-250B with a DSpark drafter, measured against plain autoregressive decoding at six operating points, three runs each.

Speedup at six operating points, falling along both the context and concurrency axes
Speedup at six operating points, falling along both the context and concurrency axes

Two axes, and they multiply. Going from concurrency 1 to concurrency 8 costs about 26%. Going from an 8–16K context to an 80–128K one costs about 31%. Together they take 2.33× down to 1.16×.

Nothing about the drafter changed between the top-left cell and the bottom-right one. Both numbers are correct. Only one of them describes a deployment.

The same technique can win big and then lose

On GLM-5.2 with the same drafter family, a single-stream request gets 2.99×, with mean accepted length 4.44, up from 1.93 with the model's built-in MTP head, which is a 1.79× improvement from the drafter alone. Raise concurrency to 64 and acceptance holds, but the speedup does not: past some load the extra verification work costs more than the saved passes, and VESSL AI rolls speculation back.

That is the second theorem from earlier in this post, met in production. Speculation spends compute to buy latency. When compute is the scarce resource, there is nothing to buy it with.

The drafter behind these numbers: DSpark

The drafter in the measurements above is DSpark; both the Solar-Open2-250B and GLM-5.2 runs use this family.

DSpark is a parallel drafter. Instead of producing γ\gamma tokens one at a time, it fills the whole draft block in a single forward pass. Drafting costs one pass, so cc drops, and the ceiling 1/c1/c from the equation above rises.

The weakness of parallel drafting is that positions cannot see each other. Each position predicts without knowing which token was actually sampled before it, so where the target is torn between several continuations, incoherent combinations appear and acceptance falls. DSpark adds a light sequential correction on top, adjusting each position's logits based on the previous token. The correction costs about as much as an embedding lookup, so cc barely moves, while consistency inside the block comes back and α\alpha rises.

The last piece is scheduling. DSpark also predicts, for each position, the probability that the draft survives that far, and allocates verification budget across every request in the batch in that order. γ\gamma stops being a fixed hyperparameter and becomes a per-request value that depends on load. Given how much speedup varies across operating points, in production this piece matters as much as the drafter itself.

Where this leaves us

Speculative decoding is one equation with three parameters and a hard ceiling. Once you know your α\alpha, your cc, and the load you actually serve, you can read a new paper's abstract, work out which of the four terms it moves, and estimate what it would buy you before writing any code.

And a speedup quoted without its operating point is not a result. It is one cell of a table.

The open question is how to raise α\alpha without paying it all back in cc. Every drafter architecture since 2018 is an answer to that, with their primary differences lying in what the drafter is allowed to see before it commits to a guess.

VESSL AI

VESSL AI

Subscribe to our newsletter

Monthly insights on building AI infrastructure, the latest GPU news, and more.

By subscribing, you'll receive monthly updates from VESSL AI. You can unsubscribe anytime. See our Privacy Policy for details.

Speculative Decoding: One Equation, Four Levers | VESSL AI