Problem
MTP's temperature-0 contract is that speculative output is byte-identical to classic decode. It is not, on qwen3.8-27b-4bit on an M5 Max, even with the #1189 exactness probe passing and #1199's qmv_wide switch engaged.
--temp 0 -n 120 --show-reasoning, main at 0199be00, generated span compared directly:
classic: ... normalization, and training." Need produce final detailed explanation. Need include architect...
mtp: ... normalization, and training." Need provide detailed explanation. Need final only. Need likely...
^ diverges at char 159 of 630
One token flips ("produce" / "provide") and the continuation is a different generation from there.
What it is not
| control |
result |
| classic run twice |
identical |
| MTP run twice |
identical |
classic with and without MLXCEL_QMV_WIDE=0 |
identical |
MTP with #1199's switch vs qmv_wide forced on |
identical |
MTP at --draft-block-size 2 vs 3 |
identical |
Why the probe misses it
models::speculative_exactness's module docs already say a passing probe is evidence rather than proof, and this is that caveat cashing out. The probe compares one verify block against one single-token chain from one synthetic state, three draws deep. The contract is a claim about a whole generation from the real sequence of states the decode actually visits. The first is passing here; the second is not.
That gap is the real defect. A gate whose green light does not imply the property it gates is worse than one that is merely conservative, because #1199 now ships MTP on generation 15+ on the strength of it.
Suspects not yet examined
Width independence is the strongest clue: the difference survives when the block is as narrow as it can be, so look at what the MTP path does that classic does not do at all rather than what it does per block.
- The seed prefill (
prefill_seed_ms is ~160 ms in the round-loop diagnostics), which runs a target forward classic decode never runs.
- Cache state after a partial-accept rollback, versus a cache that only ever grew by one.
- The accept hook's target-hidden read, if it forces an evaluation ordering the classic path does not.
Acceptance criteria
Refs #1189, #1186, #1199
Problem
MTP's temperature-0 contract is that speculative output is byte-identical to classic decode. It is not, on
qwen3.8-27b-4biton an M5 Max, even with the #1189 exactness probe passing and #1199'sqmv_wideswitch engaged.--temp 0 -n 120 --show-reasoning,mainat0199be00, generated span compared directly:One token flips ("produce" / "provide") and the continuation is a different generation from there.
What it is not
MLXCEL_QMV_WIDE=0qmv_wideforced on--draft-block-size 2vs 3qmv_widekernel split (perf(speculative): recover MTP throughput on Apple GPU generation 15+ without giving up temperature-0 byte-identity #1187). Turning the switch off changes MTP's output not at all, so the thing feat(speculative): let the MTP gate buy back exactness by dropping qmv_wide #1199 fixed is not the thing breaking this.MLXCEL_GDN_CHAIN_PARITYdefaults on, and the shape-fallback warning inmodels::gated_deltadoes not fire on this checkpoint, so the parity kernel is being taken.Why the probe misses it
models::speculative_exactness's module docs already say a passing probe is evidence rather than proof, and this is that caveat cashing out. The probe compares one verify block against one single-token chain from one synthetic state, three draws deep. The contract is a claim about a whole generation from the real sequence of states the decode actually visits. The first is passing here; the second is not.That gap is the real defect. A gate whose green light does not imply the property it gates is worse than one that is merely conservative, because #1199 now ships MTP on generation 15+ on the strength of it.
Suspects not yet examined
Width independence is the strongest clue: the difference survives when the block is as narrow as it can be, so look at what the MTP path does that classic does not do at all rather than what it does per block.
prefill_seed_msis ~160 ms in the round-loop diagnostics), which runs a target forward classic decode never runs.Acceptance criteria
Refs #1189, #1186, #1199