perf(qwen36): Q8_0→Q4_K requant of full-attention q/o projections#353
Merged
skyrocket2026 merged 1 commit intoJul 12, 2026
Merged
Conversation
65bd886 to
d1192b3
Compare
Member
✅ sparkinfer auto-eval —
|
| metric | value |
|---|---|
| label | eval:XL |
| Qwen3.5 score | eval-qwen35:none (pass) |
| Qwen3.6 score | eval-qwen36:XL (pass) |
| Qwen3.5 vs same-box main | 293.34 tok/s → +0.5% (+1.6) |
| Qwen3.5 scored decode (512 ctx · 512-context) | 294.93 tok/s |
| Qwen3.5 correctness | top-1 95.3% · KL 0.0265 |
| Qwen3.5 128-token no-regression gate | 298.92 tok/s vs main 298.46 tok/s · pass |
| Qwen3.5 512-context no-regression gate | 294.93 tok/s vs main 293.34 tok/s · pass |
| Qwen3.5 4k-context no-regression gate | 283.89 tok/s vs main 283.3 tok/s · pass |
| Qwen3.6 vs same-box main | 412.09 tok/s → +3.7% (+15.4) |
| Qwen3.6 scored decode (128 ctx · 128-context) | 427.54 tok/s |
| Qwen3.6 correctness | top-1 94.7% · KL 0.0208 |
| Qwen3.6 128-token no-regression gate | 427.54 tok/s vs main 412.09 tok/s · pass |
| Qwen3.6 512-context no-regression gate | 432.23 tok/s vs main 418.61 tok/s · pass |
| Qwen3.6 4k-context no-regression gate | 414.9 tok/s vs main 402.5 tok/s · pass |
| Qwen3.6 16k-context no-regression gate | 409.12 tok/s vs main 399.25 tok/s · pass |
| Qwen3.6 32k-context no-regression gate | 391.48 tok/s vs main 382.52 tok/s · pass |
| Qwen3.5 optimize | eval:none · 294.93 tok/s · pass |
| Qwen3.5 optimize — Qwen3.6-35B-A3B guard accuracy | top-1 94.7% · KL 0.0208 · pass |
| Qwen3.5 optimize — Qwen3.6-35B-A3B 128 | 426.27 tok/s · pass |
| Qwen3.5 optimize — Qwen3.6-35B-A3B 512 | 432.16 tok/s · pass |
| Qwen3.5 optimize — Qwen3.6-35B-A3B 4k | 415.0 tok/s · pass |
| Qwen3.5 optimize — Qwen3.6-35B-A3B 16k | 408.99 tok/s · pass |
| Qwen3.5 optimize — Qwen3.6-35B-A3B 32k | 391.23 tok/s · pass |
| Qwen3.6 optimize | eval:XL · 427.54 tok/s · pass |
| Qwen3.6 optimize — Qwythos-9B (Q4_K_M) guard accuracy | top-1 95.3% · KL 0.0265 · pass |
| Qwen3.6 optimize — Qwythos-9B (Q4_K_M) 128 | 299.02 tok/s · pass |
| Qwen3.6 optimize — Qwythos-9B (Q4_K_M) 512 | 294.37 tok/s · pass |
| Qwen3.6 optimize — Qwythos-9B (Q4_K_M) 4k | 283.43 tok/s · pass |
Verified speedup over same-box origin/main — 427.54 tok/s (main was 412.09 tok/s).
RTX 5090 (sm_120) · 128/512/4k/16k/32k guarded · scored vs same-box main · strongest context scores · built from source · correctness vs llama.cpp. Automated — not merged; merge manually after review.
Member
|
✅ Auto-merged as the round's |
1 task
skyrocket2026
added a commit
that referenced
this pull request
Jul 12, 2026
* dashboard: PR #345 -> eval:none (412.32 tok/s) * dashboard: PR #353 -> eval:XL (427.54 tok/s) * dashboard: PR #353 merged -> bidir frontier update * dashboard: use Hugging Face logo for Qwen3.5 model link Replace the org avatar with the official yellow HF icon so the Qwythos repo link is recognizable on file:// and GitHub Pages.
inference2026
added a commit
to inference2026/sparkinfer
that referenced
this pull request
Jul 13, 2026
…attn_gate) (+11.5% @128) Qwen3.6-35B-A3B UD ships the Gated-DeltaNet input projections — attn_qkv (wqkv) and attn_gate (the z gate) — as Q8_0 on all 30 GDN layers. These are the single largest per-token weight read in decode, larger than the full-attention q/o of gittensor-ai-lab#353 or the ssm_out of gittensor-ai-lab#355. Requantizing both to Q4_K once at model load reads ~47% fewer bytes on those matvecs. No decode-kernel change: after the stored type flips Q8_0→Q4_K, the GDN qkv+z projection already branches on tensor type and routes through the existing Q4_K fused kernel (launch_mmvq_gdn_qkv_z_pack2) automatically. The fit reuses the merged Lloyd-max coordinate-descent Q4_K quantizer (proj_q4k_lloyd.cu) — high enough quality to keep all 30 GDN layers inside the accuracy gate (an affine fit does not). Gated to the Qwen3.6 fingerprint; a strict no-op on every other model. Extends the existing SPARKINFER_ATTN_REQUANT_Q4K mode — set it to "attn_q,attn_output" to restore the gittensor-ai-lab#353-only behavior. Decode tok/s (RTX 5090, same-binary A/B vs gittensor-ai-lab#353-only baseline): 128: 437.57 -> 488.08 +11.54% 4096: 415.79 -> 461.19 +10.92% 16384: 410.65 -> 455.78 +10.99% 32768: 394.31 -> 433.94 +10.05% Correctness (natural text, 1500 teacher-forced positions, Q4_K vs Q8_0 baseline): top-1 96.3% (gate >= 0.90), KL 0.021 (gate <= 0.20), PPL 2.820 vs 2.788.
Merged
5 tasks
inference2026
added a commit
to inference2026/sparkinfer
that referenced
this pull request
Jul 13, 2026
…attn_gate) (+11.5% @128) Qwen3.6-35B-A3B UD ships the Gated-DeltaNet input projections — attn_qkv (wqkv) and attn_gate (the z gate) — as Q8_0 on all 30 GDN layers. These are the single largest per-token weight read in decode, larger than the full-attention q/o of gittensor-ai-lab#353 or the ssm_out of gittensor-ai-lab#355. Requantizing both to Q4_K once at model load reads ~47% fewer bytes on those matvecs. No decode-kernel change: after the stored type flips Q8_0→Q4_K, the GDN qkv+z projection already branches on tensor type and routes through the existing Q4_K fused kernel (launch_mmvq_gdn_qkv_z_pack2) automatically. The fit reuses the merged Lloyd-max coordinate-descent Q4_K quantizer (proj_q4k_lloyd.cu) — high enough quality to keep all 30 GDN layers inside the accuracy gate (an affine fit does not). Gated to the Qwen3.6 fingerprint; a strict no-op on every other model. Extends the existing SPARKINFER_ATTN_REQUANT_Q4K mode — set it to "attn_q,attn_output" to restore the gittensor-ai-lab#353-only behavior. Decode tok/s (RTX 5090, same-binary A/B vs gittensor-ai-lab#353-only baseline): 128: 437.57 -> 488.08 +11.54% 4096: 415.79 -> 461.19 +10.92% 16384: 410.65 -> 455.78 +10.99% 32768: 394.31 -> 433.94 +10.05% Correctness (natural text, 1500 teacher-forced positions, Q4_K vs Q8_0 baseline): top-1 96.3% (gate >= 0.90), KL 0.021 (gate <= 0.20), PPL 2.820 vs 2.788.
6 tasks
inference2026
added a commit
to inference2026/sparkinfer
that referenced
this pull request
Jul 13, 2026
Re-benchmarked on RTX 5090 (75.152.195.46). vs gittensor-ai-lab#353-only main on same box: 128: 438.9 -> 489.3 tok/s (+11.5%) 512: 432.2 -> 481.7 tok/s (+11.4%) 4k: 415.7 -> 461.2 tok/s (+10.9%) 16k: 411.0 -> 455.6 tok/s (+10.9%) 32k: 394.2 -> 433.6 tok/s (+10.0%) Correctness (fuzzed prompt, teacher-forced vs llama.cpp): top-1 93.6%, KL 0.026 (gate >= 90%, <= 0.20). Full evaluate.sh + bidir harness pass locally. Prior eval:REJECT (top1=0, kl=99) was accuracy.sh infra failure, not model regression.
6 tasks
skyrocket2026
pushed a commit
that referenced
this pull request
Jul 13, 2026
…attn_gate) (+11.5% @128) (#267) * perf(qwen36): Q8_0→Q4_K requant of GDN input projections (attn_qkv + attn_gate) (+11.5% @128) Qwen3.6-35B-A3B UD ships the Gated-DeltaNet input projections — attn_qkv (wqkv) and attn_gate (the z gate) — as Q8_0 on all 30 GDN layers. These are the single largest per-token weight read in decode, larger than the full-attention q/o of #353 or the ssm_out of #355. Requantizing both to Q4_K once at model load reads ~47% fewer bytes on those matvecs. No decode-kernel change: after the stored type flips Q8_0→Q4_K, the GDN qkv+z projection already branches on tensor type and routes through the existing Q4_K fused kernel (launch_mmvq_gdn_qkv_z_pack2) automatically. The fit reuses the merged Lloyd-max coordinate-descent Q4_K quantizer (proj_q4k_lloyd.cu) — high enough quality to keep all 30 GDN layers inside the accuracy gate (an affine fit does not). Gated to the Qwen3.6 fingerprint; a strict no-op on every other model. Extends the existing SPARKINFER_ATTN_REQUANT_Q4K mode — set it to "attn_q,attn_output" to restore the #353-only behavior. Decode tok/s (RTX 5090, same-binary A/B vs #353-only baseline): 128: 437.57 -> 488.08 +11.54% 4096: 415.79 -> 461.19 +10.92% 16384: 410.65 -> 455.78 +10.99% 32768: 394.31 -> 433.94 +10.05% Correctness (natural text, 1500 teacher-forced positions, Q4_K vs Q8_0 baseline): top-1 96.3% (gate >= 0.90), KL 0.021 (gate <= 0.20), PPL 2.820 vs 2.788. * re-eval: verify Qwen3.6 accuracy passes after rebase to ce33e7f Re-benchmarked on RTX 5090 (75.152.195.46). vs #353-only main on same box: 128: 438.9 -> 489.3 tok/s (+11.5%) 512: 432.2 -> 481.7 tok/s (+11.4%) 4k: 415.7 -> 461.2 tok/s (+10.9%) 16k: 411.0 -> 455.6 tok/s (+10.9%) 32k: 394.2 -> 433.6 tok/s (+10.0%) Correctness (fuzzed prompt, teacher-forced vs llama.cpp): top-1 93.6%, KL 0.026 (gate >= 90%, <= 0.20). Full evaluate.sh + bidir harness pass locally. Prior eval:REJECT (top1=0, kl=99) was accuracy.sh infra failure, not model regression.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
One load-time weight requantization for the Qwen3.6 decode path, gated to the Qwen3.6 fingerprint and off by default on every other model.
Q8_0 → Q4_K full-attention q/o. Qwen3.6-35B-A3B UD ships the full-attention query and output projections (
attn_q,attn_outputon the 10 full-attn layers) as Q8_0 — 34 bytes/block on the per-token weight read. At short context, where weight bandwidth dominates decode, those matvecs are a measurable slice of the token. This requantizes them to Q4_K once at model load and decodes them through the existing int8 dp4a Q4_K MMVQ path — ~47% fewer bytes on those reads. No decode-kernel changes: the q/o projection sites already branch on the stored tensor type, so flipping Q8_0→Q4_K at load routes them throughlaunch_mmvq_q4kautomatically.The fit is a new Lloyd-max coordinate-descent Q4_K quantizer (
proj_q4k_lloyd.cu): each 32-value group alternates nearest-code assignment with a joint weighted least-squares solve for (scale, min) to convergence, then re-fits the 4-bit codes against the quantized super-block levels. It is applied only to the Q8_0 attention path; the Q6_K dense-FFN down requant keeps its existing affine fit.On by default for the Qwen3.6 fingerprint (
is_qwen35_or_qwen36_hybrid_moe); a strict no-op on the dense Qwythos path and any non-matching model.A/B toggle:
SPARKINFER_ATTN_REQUANT_Q4K=offrestores native Q8_0 reads for the comparison below.Proof of speedup
sm_120)Decode tok/s (end-to-end,
qwen3_gguf_bench,Qwen3.6-35B-A3B-UD-Q4_K_M.gguf, 128 decode tokens), default vsSPARKINFER_ATTN_REQUANT_Q4K=off, same binary:=off, native Q8_0)128 and 512 are the strongest contexts (short context is weight-bandwidth bound). 4k/16k/32k are neutral-to-positive — a byte-reducing requant cannot slow decode; the win just shrinks as KV work grows. Qwythos-9B is unchanged (no-op).
Accuracy. The requant is lossy but confined to the accuracy-tolerant attention projections (
attn_qfeeds q-norm + softmax;attn_outputis an output proj). Teacher-forced top-1 agreement vs the native-Q8 baseline is 277/292 = 0.948 on a held-out text window; subject to the harness KL/top-1 gate (bench/scripts/accuracy.sh, top-1 ≥ 0.90, KL ≤ 0.20).Relation to open PRs
The Q8_0→Q4_K requant of the full-attention q/o projections with the Lloyd-max fit is original — no open or merged PR does it. The two kernel files (
kernels/csrc/cuda/quant/proj_q4k_lloyd.cu,proj_requant.h) are new paths touched by no other PR. The only shared file isruntime/src/models/qwen35.cpp(+16/−4). Added-line containment against every requant PR on that file is well under the guard thresholds: #350 = 15.4%, #323 = 33.0% (highest), #329/#308/#338 ≈ 0% (block ≥ 85%, warn ≥ 75%); per-function max is 77.6% on the format-dictated ggml Q4_K super-block packing, below the 92% single-function warn. The shared lines are generic CUDA launcher boilerplate. Distinct from #350 (Q8→Q4 on the GDNattn_qkv/attn_gateviamake_qkx2): different layer class, different fitter, new file.