Repository navigation
qwen3_5 cuda: serve dense EXL3 checkpoints with the DFlash2 drafter - #1474
diwakergupta wants to merge 1 commit into
Conversation
…on CUDA Admit non-MoE qwen3_5 EXL3 checkpoints (pocketed ones stay refused), load the dense SwiGLU MLP as EXL3 linears, allocate the grouped-expert scratch only for MoE geometry, and let openDrafter attach DFlash2 to EXL3 targets. The drafter reads the target's EXL3 head over its two vocabulary spans through exl3.Weight.columns, a view of whole 128-column blocks with the parent's strides, sharing the packing path with the affine head. Docs: the 27B recipe's native EXL3 section, exl3.md and cuda.md no longer say the native engine serves no EXL3 pack.
|
Thanks @diwakergupta, and thanks for splitting #1407 up so quickly. Unfortunately this part now overlaps #1465, which makes the same change: the dense admission in Two things here aren't in #1465, and we'd welcome them as one small PR on top of it:
Please keep #1465's refusal for MoE EXL3 targets. This branch removes it from both |
What this changes
The native CUDA
qwen3_5engine now serves dense EXL3 checkpoints (turboderp'sQwen3.8-27B-exl3) and attaches the DFlash2 drafter to EXL3 targets. This is part (a) of the split of #1407 that @ashhart suggested; (b) prompt tiles, (c) memory and (d) copy policy follow as separate PRs.cuda_geometry.zig: admits non-MoEqwen3_5EXL3 checkpoints (pocketed ones are still refused).cuda_exl3_weights.zig: loads the dense SwiGLU MLP (mlp.{gate,up,down}_proj) as EXL3 linears, and allocates the grouped-expert scratch only for MoE geometry.cuda_native.zig: listsexl3in the family's formats, andopenDrafterno longer refuses EXL3 targets.cuda_draft_frame.zig: the drafter reads the target's EXL3 head over its two vocabulary spans as column views of the stored matrix. It uses the same packing path as the affine head.exl3.zig: addsWeight.columns(from, n), a view of whole 128-column blocks that keeps the parent's strides, with a host test.exl3.mdandcuda.mdno longer say the native engine serves no EXL3 pack.Licences:
turboderp/Qwen3.8-27B-exl3is Apache-2.0 (baseQwen/Qwen3.8-27B), and the drafterz-lab/Qwen3.8-27B-DFlash2is Apache-2.0. No code or tables were taken from other engines.Receipt
sm_86, CUDA 13.1 nvcc),zig build native -Dsm=86. Checkpointturboderp/Qwen3.8-27B-exl3branch3.50bpw(rev8351c54e), drafterz-lab/Qwen3.8-27B-DFlash2(rev50307d4c) at--drafter-bits 4. bf16 KV cache (default),--context 32768, one rank. The binary was built from this branch before its rebase ontoee896951; the rebase changed no file in this PR."draft": falseand concurrent vs solo.tools/bench_concurrent.py --levels 2 --tokens 256 --alone --serial, greedy and sampled:aloneandserialchecks equal, none unequal or failed.--promptswith two long prompts (5,080 and 2,278 tokens, so one spans a 4,096-row cut): all equal./tokenize). Each tail length runs greedy and seeded-sampled, 128 tokens.cached_tokens4096. The fresh runs went to a restarted server and reportedcached_tokens0.token_sha256was equal in all 8 cases.bench_concurrent, per-stream tok/s): code 155 / 122 (sampled / greedy), chat 86 / 90. There is no baseline:mainrefuses this checkpoint.main's EXL3 path; cold prefill of an 8k prompt is 14.5 s here, and (b) changes it.zig build test test-kernel-contract test-golden test-server-security test-pull-security fuzz-cortheon test-cuda-host: exit 0, 447/447 build steps succeeded with the same single skip asmainatee896951.python3 tools/zig/lean_new.pyagainst the base: 0 new problems.sm_121. The Qwen3.5-MoE EXL3 checkpoints: no copy here, but their prompt and decode code paths are unchanged.Checklist
"draft": false, a resumed prompt equals a fresh one, and concurrent equals solo.sm_86only; Metal and GB10 not run.Weight.columnshost test, and the EXL3 dense admission inqwen35_formats_host.zig.