Qwen3.8 DFlash2 benchmark against Optimized Speed and Quality MTP - #304
Qwen3.8 DFlash2 benchmark against Optimized Speed and Quality MTP#304davidtai wants to merge 16 commits into
Conversation
Complete Qwen3.8 DFlash2 benchmark campaignThis comment records every benchmark run used to narrow the stock DFlash2 depth, including the invalid 64K attempt and its corrected replacement. No custom DFlash2 kernel was built; the purpose of this campaign was to choose the depth first. Fixed setup
1. Initial exhaustive 1K/1K sweepThis was the reference MTP bracket and first complete physical-width sweep. It established K=3 / M=4 as the short-context winner.
Receipt SHA-256: 2. Narrowed 1K/1K K=4..6 repeatThis repeat checked the cluster around the apparent K=5 secondary peak.
Receipt SHA-256: 3. 16K/1K K=4..6This used an actual 16,384-token Python prompt, not a warmed cache with a shorter measured input. Longer context changed the ranking: deeper blocks became progressively better.
Receipt SHA-256: 4. Standalone 16K/1K K=7We then tested the checkpoint maximum: physical M=8 / accepted K=7.
Receipt SHA-256: 5. Joined 16K/1K K=3..7 sweepThe standalone K=7 result was then joined into one same-load, same-rotation sweep so the K=3..7 ranking did not depend on separate process windows.
Receipt SHA-256: 6. Naturalistic 109-token Python prompt, 1,024 output tokensThis used a normal request to implement and test
Receipt SHA-256: 7. Invalid “1K vs 64K” attempt — retained and explicitly rejectedThis was supposed to measure 64K prefill with 1,024 generated tokens, but the receipt proves
Rejected receipt SHA-256: 8. Corrected cold 64K/1K K=3..7 sweepThe replacement run fed an actual cold 65,536-token Python prompt and generated exactly 1,024 tokens for every arm. At 64K, K=3 / M=4 becomes the clear winner even though deeper widths have higher acceptance rates. This is the depth to beat before considering a custom kernel for the 64K workload.
Receipt SHA-256: 9. Full paired HumanEval+We generated one completion for all 164 HumanEval+ tasks with both engines from the same loaded target. We used the EvalPlus 0.3.1 OpenAI chat prompt, thinking disabled, greedy top-k-1 sampling, seed 0, EOS stopping, and a 768-token cap. The programs were sanitized with EvalPlus itself, then the MTP and DFlash2 sample sets were scored concurrently with four evaluator workers each. For quality we used the 64K throughput winner, K=3 / M=4.
Comparison receipt SHA-256: ConclusionStock DFlash2 is materially faster than the optimized MTP control for K>=2 on most measured prompts, but the best width is workload-dependent:
The 64K result answers the immediate selection question: optimize K=3/M=4 first if we proceed to a custom kernel for that workload. The HumanEval+ result says performance promotion should carry a quality caveat: one fewer pass out of 164, with no compensating DFlash-only win in this deterministic run. |
Optimized-Quality cold-prefix rerunI reran the DFlash2 depth matrix against the Quality target artifact, using the new pinned/reproducible runner in Exact artifacts and runtime contract
The benchmark was run inside the verified GPU-lock guard. The normal Qwen service was stopped for the measurement window, the lock was held continuously, and Workloads and methodThere are four independently measured workloads:
The cold-prefix generator repeats/truncates the repository's coding-agent prefill text to the exact requested prefix length. It constructs the 1,024-token test suffix separately, then concatenates the two token arrays. All three cold rows use the exact same suffix hash:
No prefix/session cache was reused. DFlash ran with prefix caches disabled and cache boundaries cleared. The MTP controls used no session bank. For each workload and K, there were three rotated repetitions. Each candidate was bracketed by the unchanged Quality MTP control:
The tables report:
DFlash's public K is one less than its physical width, so K=1..7 maps to physical M=2..8. Natural Python, 105 input / 1,024 output
Selection: K=5. Cold 1K prefix + fixed 1K test, 2,048 input / 1,024 output
Selection: K=5. Cold 16K prefix + fixed 1K test, 17,408 input / 1,024 output
Selection: K=4 has the highest median decode TPS; the prespecified normalized-ratio tolerance classifies K=4 and K=5 as a tie. Cold 64K prefix + fixed 1K test, 66,560 input / 1,024 output
Selection: K=3. K=5 is close by raw median decode TPS, but K=3 wins the prespecified bracket-normalized selection rule. Correctness and interpretation
The central result is that there is no single best DFlash depth across context lengths. K=5 wins the short workloads, K=4/K=5 are the 16K frontier, and K=3 wins at 64K. Higher K keeps raising speculative hit rate, but after the context-dependent optimum the extra verification work costs more than the additional accepted draft tokens save. This argues for a construction-time/context-phase route rather than a single globally hard-coded width. Receipt hashes
Verification
Implementation commit: |
What changed
This adds a closed, benchmark-only Qwen3.8 DFlash2 channel against the existing MTPLX Optimized-Speed target:
z-lab/Qwen3.8-27B-DFlash2;Why
We wanted to establish the best stock DFlash2 depth on the real Qwen3.8 27B model before considering any custom width-specific Metal kernel. The comparison must reuse the promoted MTPLX Optimized-Speed profile and target model, replacing only the speculative proposer. This PR provides that controlled measurement lane; it does not promote DFlash2 into serving defaults and does not add a custom kernel.
Notable decisions
Youssofal/Qwen3.8-27B-MTPLX-Optimized-Speedonly.z-lab/Qwen3.8-27B-DFlash2at revision50307d4c4cde6860d4eee73e2547cd786fe8e8a4.davidtai/dflash-mlx@95a16104c5462793f9f14d2cd0b97b856fb643a1, which contains the cache-ownership correction needed when alternating MTPLX MTP and DFlash2 against one shared target.temperature=1.0,top_p=1.0,top_k=1, seed 0. Thinking is disabled.Mis DFlash2 physical block width; accepted draft depth isK=M-1. The checkpoint supports physical widths through M=8, therefore K=1 through K=7 are the meaningful speculative candidates.eligible-or-stockor exception fallback.How to verify
uv sync --extra dev --extra competitors python -m pytest -q \ tests/test_dflash2_dependency.py \ tests/test_dflash2_contract.py \ tests/test_dflash2_runtime.py \ tests/test_dflash2_depth_sweep.py \ tests/test_dflash2_cli.py \ tests/test_qwen38_dflash2_depth_guarded.py ruff check \ mtplx/benchmarks/dflash2_contract.py \ mtplx/benchmarks/dflash2_runtime.py \ mtplx/benchmarks/runners/competitor_baselines.py \ mtplx/benchmarks/runners/dflash2_depth_sweep.py \ mtplx/cli.py scripts/qwen38_dflash2_depth_guarded.py \ tests/test_dflash2_*.py tests/test_qwen38_dflash2_depth_guarded.py scripts/hygiene_scan.sh uv lock --check python -m build scripts/fresh_venv_smoke.shThe full suite is green with one pre-existing upstream race deselected:
The deselected test fails identically on unchanged
upstream/main(2b0360ca) because its connection spy also counts an asynchronous cold-tier background scan. It fails 3/3 on that exact base and is untouched by this branch.The complete guarded benchmark campaign and HumanEval+ results are in the PR benchmark comment.