What
The binding cross-engine A/B against the pinned, graphed oracle
(0.23.1rc1.dev1511+g555967922, FlashInfer 0.6.15.post1) is recorded in
.agents/specs/dspark-spec-decode.md §6h. It splits into two verdicts:
- 35B A3B MoE lane: near parity. 0.92–0.98x cross-engine, and our
acceptance MATCHES upstream: 20.8% vs 20.4% (212/1040, 1.63 accepted per
draft of k=8).
- 27B dense lane: the gap, and it is DRAFT QUALITY. Upstream accepts
49.3% (281/570, 7.39 accepted per draft of k=15) where we accept
12.2% (~1.8 per draft). Upstream turns that into a 5.23x self-speedup on
the "capital" prompt; we get 1.76x. Cross-engine that cell is 0.350x
(17.41 vs 49.71 tok/s).
Warm tok/s, completion_tokens / whole-request wall on both sides, same
target+draft+k, max_num_seqs=2, greedy, one flock, cold run discarded.
| lane / prompt |
ours |
pinned vLLM |
ours/vLLM |
| 35B spec-off, "capital" (128 tok both) |
71.47 |
73.91 |
0.967x |
| 35B DSpark k=8, "capital" (128 tok both) |
74.10 |
75.92 |
0.976x |
| 35B DSpark k=8, "fibonacci" (89 tok both) |
134.85 |
146.41 |
0.921x |
| 27B spec-off, "fibonacci" (126 tok both) |
9.80 |
9.51 |
1.031x |
| 27B DSpark k=15, "fibonacci" |
31.83 |
34.06 |
0.935x |
| 27B DSpark k=15, "capital" |
17.41 |
49.71 |
0.350x |
Ruled out (checked, not assumed)
- Mis-resolved aux taps. The 27B draft declares five taps at absolute
target indices [1, 16, 31, 46, 61], and the 27B target is a hybrid
(linear-attention + full-attention), so a tap resolved against a filtered
layer list would silently degrade drafts. Both MaybeCaptureAuxTap call
sites are inside the full for (l = 0; l < num_hidden_layers; ++l) loop and
index by absolute l (qwen3_5.cpp:6707, :7546).
- The Markov step loop, which matches upstream's shape:
prev seeded from
the anchor, re-biased per step, argmax over base + bias, then d2t
(speculator.py:120-121,148).
Next traceable hypothesis
The 27B draft uses the flat/native config layout and carries no
draft_vocab_size; the 35B carries 32000 and reaches upstream-matching
acceptance through the Speculators translation path. So the d2t / reduced-vocab
handling on the flat path is the thing to instrument next — compare our
proposed draft token ids against upstream's for an identical prefix, rather
than comparing acceptance totals.
No ceiling is being claimed here: upstream demonstrably extracts 7.39 tokens
per draft from the same checkpoint on the same hardware.
Also fixed in passing
The first run of this A/B measured the wrong oracle: ~/venvs/vllm-oracle
is a symlink to the preserved v0.25.0-stage rollback (issue #375's failure
mode). The harness now asserts vLLM commit + FlashInfer version and aborts on
mismatch. The rollback misleads in both directions — its DSpark is far slower
than the pin's (35B 89.8 vs 146.4 tok/s).
What
The binding cross-engine A/B against the pinned, graphed oracle
(
0.23.1rc1.dev1511+g555967922, FlashInfer 0.6.15.post1) is recorded in.agents/specs/dspark-spec-decode.md§6h. It splits into two verdicts:acceptance MATCHES upstream: 20.8% vs 20.4% (212/1040, 1.63 accepted per
draft of k=8).
49.3% (281/570, 7.39 accepted per draft of k=15) where we accept
12.2% (~1.8 per draft). Upstream turns that into a 5.23x self-speedup on
the "capital" prompt; we get 1.76x. Cross-engine that cell is 0.350x
(17.41 vs 49.71 tok/s).
Warm tok/s,
completion_tokens / whole-request wallon both sides, sametarget+draft+k,
max_num_seqs=2, greedy, one flock, cold run discarded.Ruled out (checked, not assumed)
target indices
[1, 16, 31, 46, 61], and the 27B target is a hybrid(linear-attention + full-attention), so a tap resolved against a filtered
layer list would silently degrade drafts. Both
MaybeCaptureAuxTapcallsites are inside the full
for (l = 0; l < num_hidden_layers; ++l)loop andindex by absolute
l(qwen3_5.cpp:6707,:7546).prevseeded fromthe anchor, re-biased per step, argmax over
base + bias, thend2t(
speculator.py:120-121,148).Next traceable hypothesis
The 27B draft uses the flat/native config layout and carries no
draft_vocab_size; the 35B carries 32000 and reaches upstream-matchingacceptance through the Speculators translation path. So the d2t / reduced-vocab
handling on the flat path is the thing to instrument next — compare our
proposed draft token ids against upstream's for an identical prefix, rather
than comparing acceptance totals.
No ceiling is being claimed here: upstream demonstrably extracts 7.39 tokens
per draft from the same checkpoint on the same hardware.
Also fixed in passing
The first run of this A/B measured the wrong oracle:
~/venvs/vllm-oracleis a symlink to the preserved
v0.25.0-stagerollback (issue #375's failuremode). The harness now asserts vLLM commit + FlashInfer version and aborts on
mismatch. The rollback misleads in both directions — its DSpark is far slower
than the pin's (35B 89.8 vs 146.4 tok/s).