Summary
MTP (multi-token prediction) speculative decoding experiences dramatic draft acceptance rate collapse at specific context sizes in llama-server. A 256-token context difference can mean the difference between a 2.1x speedup and 1.04x (near-zero acceptance). The pattern repeats at ~2048-aligned boundaries, suggesting an internal KV cache buffer alignment issue in the MTP draft context.
Hardware
- GPU: NVIDIA GeForce RTX 5060 Ti 16GB (SM120 Blackwell, 16311 MiB usable)
- CPU: AMD Ryzen 5 7600
Software
- llama.cpp b9295 (95405ac): MTP works correctly at small contexts
- llama.cpp b9305 (63248fc): Includes fit-margin commit 83eebe9
- Build:
CMAKE_BUILD_TYPE=Release, LLAMA_CUDA=ON, CMAKE_CUDA_ARCHITECTURES=120
- KV cache:
--cache-type-k q8_0 --cache-type-v q8_0
Model
- Unsloth Qwen3.6-35B-A3B-UD-IQ2_M (GGUF, 11.9 GB, 35B params, 3B active per token)
- MTP weights included (NextN architecture)
- Server flags:
-ngl 99 --spec-type draft-mtp --spec-draft-n-max 2
Reproduction
llama-server \
--model Qwen3.6-35B-A3B-UD-IQ2_M.gguf \
--ctx-size 17408 \
--cache-type-k q8_0 --cache-type-v q8_0 \
-ngl 99 \
--spec-type draft-mtp --spec-draft-n-max 2 \
--port 18888 --no-ui
Then send via HTTP API:
POST /v1/completions
{
"prompt": "<test prompt>",
"max_tokens": 256,
"temperature": 0.0,
"speculative": {"n_max": 2}
}
The collapse is triggered by --ctx-size value, NOT prompt length.
Results (b9305, q8_0 KV cache, MTP N=2)
| Context |
Baseline TG |
MTP N=2 TG |
Speedup |
AR% |
Status |
| 4096 |
103.5 |
163.9 |
1.58x |
55% |
OK |
| 8192 |
101.3 |
159.9 |
1.58x |
55% |
OK |
| 10240 |
66.0 |
69.3 |
1.05x |
7% |
BROKEN |
| 11776 |
76.6 |
76.9 |
1.00x |
0.6% |
BROKEN |
| 12000 |
33.5 |
30.4 |
0.91x |
0% |
BROKEN |
| 12032 |
76.5 |
79.9 |
1.04x |
6% |
BROKEN |
| 12288 |
74.2 |
155.5 |
2.10x |
78% |
OK |
| 12544 |
75.3 |
82.6 |
1.10x |
13% |
BROKEN |
| 12800 |
97.1 |
123.6 |
1.27x |
32% |
Partial |
| 13312 |
76.5 |
85.3 |
1.12x |
15% |
BROKEN |
| 14336 |
73.2 |
75.3 |
1.03x |
4% |
BROKEN |
| 17024 |
28.6 |
25.2 |
0.88x |
0% |
BROKEN |
| 17280 |
69.2 |
79.3 |
1.15x |
19% |
Degraded |
| 18432 |
90.5 |
152.1 |
1.68x |
61% |
OK |
Same pattern at larger context with q4_0 KV (halved size):
| Context |
Baseline TG |
MTP N=2 TG |
Speedup |
Status |
| 12288 |
75.6 |
160.6 |
2.12x |
OK |
| 22016 |
25.2 |
23.7 |
0.94x |
BROKEN |
| 22336 |
85.9 |
146.6 |
1.74x |
OK |
| 22528 |
85.3 |
106.2 |
1.25x |
Partial |
| 24064 |
25.1 |
22.3 |
0.89x |
BROKEN |
| 24576 |
84.3 |
145.7 |
1.75x |
OK |
Key Observations
-
Narrowest transition: 256 tokens between 1.04x (ctx=12032) and 2.10x (ctx=12288). A single power-of-2 boundary separates regression from peak performance.
-
Pre-dates fit-margin (b9295): Same collapse at ctx=17024 on b9295. Fit-margin commit 83eebe9 only shifted boundary positions by ~288 tokens — didn't fix the root cause.
-
Both q8_0 and q4_0 KV affected: q8_0 collapses at ctx=24576 (0.87x) but q4_0 works (1.75x). Yet both show the same ~2048-aligned structural pattern — NOT a VRAM limitation.
-
AR is KV type independent: 12288 with q4_0 KV: AR 79% (2.12x). 12288 with q8_0 KV: AR 78% (2.10x). Identical acceptance rate proves the AR collapse is in the draft context interaction, not KV quantization.
-
No crash, no OOM: Server stays operational — draft simply stops accepting predictions (silent performance bug).
-
Early EOS at collapse points (b9295): At ctx=17024 with q8_0 KV, server emits early EOS (12 tokens vs 128 requested), corrupting throughput measurements.
Expected Behavior
MTP acceptance rate should be consistent across context sizes (55-78% AR for this model). Collapses of 100x (78% → 0.6%) over 256-token boundaries indicate a structural issue in how the MTP draft context shares the KV cache with the target context.
Hypothesis
The ~256-2048 token granularity suggests an internal buffer alignment issue in slot allocation for the MTP draft context vs target context. When the KV pool boundary aligns unfavorably at specific context sizes, the draft context's slot management interferes, causing near-zero token acceptance.
Suggested Investigation
- Check how
LLAMA_CONTEXT_TYPE_MTP context is created relative to slot allocation in server-context.cpp and llama-context.cpp
- Look for power-of-2 or block-aligned boundary conditions in slot management for the draft vs target contexts
- Consider whether the combined target+draft KV cache exceeds slot capacity at specific context sizes
Summary
MTP (multi-token prediction) speculative decoding experiences dramatic draft acceptance rate collapse at specific context sizes in llama-server. A 256-token context difference can mean the difference between a 2.1x speedup and 1.04x (near-zero acceptance). The pattern repeats at ~2048-aligned boundaries, suggesting an internal KV cache buffer alignment issue in the MTP draft context.
Hardware
Software
CMAKE_BUILD_TYPE=Release, LLAMA_CUDA=ON, CMAKE_CUDA_ARCHITECTURES=120--cache-type-k q8_0 --cache-type-v q8_0Model
-ngl 99 --spec-type draft-mtp --spec-draft-n-max 2Reproduction
Then send via HTTP API:
The collapse is triggered by
--ctx-sizevalue, NOT prompt length.Results (b9305, q8_0 KV cache, MTP N=2)
Same pattern at larger context with q4_0 KV (halved size):
Key Observations
Narrowest transition: 256 tokens between 1.04x (ctx=12032) and 2.10x (ctx=12288). A single power-of-2 boundary separates regression from peak performance.
Pre-dates fit-margin (b9295): Same collapse at ctx=17024 on b9295. Fit-margin commit 83eebe9 only shifted boundary positions by ~288 tokens — didn't fix the root cause.
Both q8_0 and q4_0 KV affected: q8_0 collapses at ctx=24576 (0.87x) but q4_0 works (1.75x). Yet both show the same ~2048-aligned structural pattern — NOT a VRAM limitation.
AR is KV type independent: 12288 with q4_0 KV: AR 79% (2.12x). 12288 with q8_0 KV: AR 78% (2.10x). Identical acceptance rate proves the AR collapse is in the draft context interaction, not KV quantization.
No crash, no OOM: Server stays operational — draft simply stops accepting predictions (silent performance bug).
Early EOS at collapse points (b9295): At ctx=17024 with q8_0 KV, server emits early EOS (12 tokens vs 128 requested), corrupting throughput measurements.
Expected Behavior
MTP acceptance rate should be consistent across context sizes (55-78% AR for this model). Collapses of 100x (78% → 0.6%) over 256-token boundaries indicate a structural issue in how the MTP draft context shares the KV cache with the target context.
Hypothesis
The ~256-2048 token granularity suggests an internal buffer alignment issue in slot allocation for the MTP draft context vs target context. When the KV pool boundary aligns unfavorably at specific context sizes, the draft context's slot management interferes, causing near-zero token acceptance.
Suggested Investigation
LLAMA_CONTEXT_TYPE_MTPcontext is created relative to slot allocation inserver-context.cppandllama-context.cpp