Speculative Decoding
- 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 1halves 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
- reddit-qwen3-6-mtp-12gb โ practitioner Reddit thread, the source of the empirical numbers above
- habr-local-llm-quantization-deep-dive โ Vyacheslav's primer that catalogs all four variants
- moe-cpu-offload โ the other operational lever that combines with speculative decoding to make 12 GB consumer cards viable for 35B-class models
- local-llm-16gb-vram-tests โ the tests article doesn't enable speculative decoding; speeds reported there are sequential
- llama-cpp โ implementation site