Map

Speculative Decoding

Wiki conceptllminferencellama-cpplocal-models โ†ณ show in map Markdown
title
Speculative Decoding
type
concept
summary
Predict multiple tokens per forward pass, verify in batch โ€” four llama.cpp variants (draft model, MTP, EAGLE3, ngram-mod) trade off draft quality, memory, and applicability
tags
llm, inference, llama-cpp, local-models
created
2026-05-13
updated
2026-05-13

Speculative decoding is the technique of producing several candidate tokens cheaply and verifying them with a single batched forward pass of the main model. If the candidates are accepted, you generate multiple tokens for the cost of one forward pass; if they're rejected, you fall back to the standard sequential generation. The interesting variation is in how the candidates are produced โ€” and as of 2026, llama.cpp supports four mechanisms, each with different memory/quality tradeoffs.

The arithmetic that makes it worthwhile: producing a draft token has to be substantially cheaper than running the main model, and the acceptance rate has to be high enough that the batch verification pays off. Both depend on the workload โ€” heavily structured outputs (code, translation, math) get higher acceptance than creative writing.

The four llama.cpp variants

Draft model (--spec-type draft). Use a small sibling model from the same family โ€” same tokenizer, same vocabulary, same general style โ€” to generate draft tokens. The main model then verifies them in batch. The classical implementation. The ratio between the two models matters: the draft has to be at least ~3ร— smaller in active parameters or the overhead eats the speedup. Worked example from Vyacheslav: Gemma-4 31B UD-Q4_K_XL alone at 62 t/s; Gemma-4 31B with Gemma-4 E2B as draft, 97 t/s (~55% draft acceptance on coding workloads). Specify --parallel 1 to avoid the 4ร— memory reservation that automatic parallelism takes.

Default --draft-p-min is 0.75 โ€” accept draft tokens only when both the draft and main model are >75% confident. Some output drift is technically allowed: a token can land that the main model wouldn't itself have picked but agrees is acceptable. Lossless verification is not the default for the draft-model path.

MTP โ€” Multi-Token Prediction (--spec-type mtp). Extra prediction heads trained jointly with the model that predict several tokens ahead from the same hidden state. No separate draft model, no separate weights to load (the heads live inside the GGUF). First shipped in DeepSeek V3/R1; llama.cpp PR #22673 brought it to Qwen 3.6 and Gemma 4.

MTP at --spec-draft-n-max 2-3 is the typical configuration. janvitos's measurement on RTX 4070 Super 12GB (reddit-qwen3-6-mtp-12gb): 80+ t/s on code with 92โ€“95% draft acceptance. The dependency on context-sensitive correctness is lower than a separate draft model because the heads were trained alongside the main weights. Default verification is exact โ€” MTP doesn't allow the output drift the draft-model path does.

EAGLE3 (--spec-type eagle3). A lightweight autoregressive head bolted onto existing weights โ€” no draft model, no jointly-trained MTP heads. Reads the hidden state of the main model and predicts the next several tokens from it. Works on models that weren't designed with speculative decoding in mind. llama.cpp PR #18039. Default verification is exact.

ngram-mod (--spec-type ngram-mod). Pure-math draft from prior tokens in the same context โ€” no model, no head. Excellent when the output reproduces large chunks of the input verbatim: making a small edit to a file and emitting the rest unchanged, finding-and-replacing a variable name across a block, regenerating code with one change. llama.cpp PR #19164. This is the agentic-coding-friendly variant: when an agent loops "read file โ†’ edit โ†’ emit modified file," ngram-mod can carry most of the rewrite for free.

When each variant wins

Variant Best for Worst for Notes
Draft model Dense models, mixed workloads Small models where the ratio doesn't work Has output drift; not bit-exact
MTP Models that shipped with MTP heads (DeepSeek, Qwen 3.6, Gemma 4) Models without heads (most older ones) Exact verification
EAGLE3 Existing models without MTP heads Vision/non-text outputs Exact verification
ngram-mod Edit-heavy workloads, code with reuse Free-form generation Free; uses only context

The context-dependence

A finding from MTP measurements at long context (Still-Notice8155, reddit-qwen3-6-mtp-12gb): MTP saves roughly constant time per token regardless of context length, while attention cost grows linearly with context. So MTP's relative benefit widens as context fills up. On Qwen3.6-35B-A3B at 125K context: non-MTP ~3 t/s vs MTP+turboquant 13.6 t/s โ€” 4.5ร— speedup. At 5K context the same setup is 1.8ร— faster. This is the opposite shape from many optimizations and worth keeping in mind: MTP's payoff is biggest exactly where unmodified inference is slowest.

Draft acceptance is workload-dependent

MTP on Qwen3.6 across nine task types (janvitos's mtp-bench.py):

Task Accept rate
code_python 0.947
code_cpp 0.925
stepwise_math 0.826
qa_factual 0.826
translation 0.812
summarize 0.800
long_code_review 0.790
explain_concept 0.750
creative_short 0.694

The spread is the predictability of the output token distribution. Code with established patterns gets ~95% acceptance; open-ended prose drops to ~69%. The ranking is stable across the speculative-decoding family โ€” workloads that are friendly to MTP are also friendly to draft-model and EAGLE3 variants.

Failures and caveats

  • Vision is broken on MTP as of mid-2026. llama.cpp issues #22867 and PR #22673 thread document the current state. Stick to draft-model for multimodal.
  • Memory for the draft model is not free. --parallel 1 halves the KV cache reservation that defaults to --parallel 4; the difference can be the GB that decides whether MTP fits on the GPU.
  • Reasoning model output through speculative decoding needs --chat-template-kwargs '{"preserve_thinking": true}' so the thinking trace isn't truncated. The MTP heads in Qwen 3.6 were trained with this assumption.

Cross-references