feat: TQ4_1S weight compression (Metal only, needs CUDA port)#45
Conversation
Adds CUDA dequantization for TQ4_1S (5.0 bpv) and TQ3_1S (4.0 bpv) WHT-rotated weight compression types. These achieve 27-37% model size reduction at +1.0-1.9% PPL on Qwen/Phi families. Base types + Metal + CPU quantize/dequant from TheTom's PR TheTom#45. CUDA additions: - turbo-quant.cuh: weight centroids (N(0,1) Lloyd-Max, 16/8 levels), sign array for 32-element inverse WHT - dequantize.cuh: dequantize_tq4_1s/tq3_1s — full 32-element block inverse RHT (5 butterfly stages + normalize + unsign) - convert.cu: TQ4_1S/TQ3_1S in all 4 dequant dispatchers - ggml-cuda.cu: supports_op for MUL_MAT and GET_ROWS, excluded from mmvq/mmq (uses cuBLAS dequant-to-f16 path) The cuBLAS path is correct for initial support. Future optimization: pre-rotate activations via warp shuffle WHT (same pattern as KV cache Q rotation) to eliminate per-block inverse WHT. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Regression Test Results — PR #45Verified that the TQ4_1S weight compression PR does NOT break existing TurboQuant KV cache functionality or standard inference on non-compressed models. Hardware: M5 Max (128GB) + Mac Mini M2 Pro (32GB) Speed — No Regressions
All speeds normal or improved. No regressions. PPL — No Regressions (full wikitext-2 runs)
All PPL values match known-good. MUL_MAT_ID (MoE path) verified working. VerdictALL TESTS PASS. 5 models, 2 hardware platforms, 4 KV configs. The |
6c3e503 to
cb8bddc
Compare
turbo4 SET_ROWS was using turbo3's shared template with wrong 2+1 bit packing. New dedicated kernel_set_rows_turbo4 with correct 3-bit packed indices + QJL signs. PPL: 679 → 6.19. Also added turbo4 prefill FA kernel instantiations (non-vec path). QJL ablation finding: disabling QJL improves PPL from 6.1894 to 6.1756 (identical to turbo3). QJL correction hurts quality in attention context. Consistent with scos-lab issue #45. Co-Authored-By: tturney@psyguard.ai Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Update: Rebased on upstream master + regression testBranch force-pushed. Now rebased on latest
Upstream conflict: activation rotation (commit 744c0c7)Upstream added graph-level Hadamard rotation for KV cache quantization (
Fix: disabled upstream rotation by default in our fork. Users can re-enable with Regression test (M5 Max, rebased branch cb8bddc)
All tests pass. No regressions. Phi-4 crash resolved. |
|
CUDA port available on our branch: signalnine/llama-cpp-turboquant What's implemented:
Results (Qwen2.5-7B TQ4_1S, RTX 5090):
The fused kernel pre-rotates the activation vector once per mul_mat via Happy to iterate on this if you have ideas for closing the CUDA gap further. |
|
This is great work, thank you for turning this around so fast. PPL matching between cuBLAS and fused confirms correctness. One question before we merge: can you confirm that uncompressed models (q8_0, q4_0, etc.) show no decode regression on this branch? i.e. the new code paths only activate for TQ4_1S/TQ3_1S and existing quant types run at the same speed as before the PR. |
CUDA kernel review — performance improvement opportunitiesNice work on the V8 pre-rotation approach. PPL matching confirms correctness. Here's what I see for closing the gap from 39% to 70-85% of q8_0: High priority (biggest decode wins)
Medium priority
Skip / low value
Realistic ceilingPer architecture with full tuning (NR0 + load dedup + vectorized + batch):
The 39% → 70-85% gap is primarily data reuse, not math precision. The pre-rotation design is correct — it just needs the activation tile shared across more rows per CTA. |
Full Regression Test — PR #45 (cb8bddc)Hardware
Quantize tool verification
M5 Max — Uncompressed weights + TurboQuant KVQwen2.5-1.5B Q8_0
Phi-4 14B Q8_0 (crash fix verification)
No crash. Upstream attn_rot disabled by default (commit cb8bddc). Qwen3.5-27B Q8_0
Qwen3.5-35B MoE Q8_0 (MUL_MAT_ID path)
M5 Max — TQ4_1S Weight CompressionQwen2.5-1.5B Config I (1.28 GiB, 6.20 BPW)
Mac Mini M2 Pro — Qwen2.5-7B Q4_K_M
Summary
All tests pass. PR is safe for review. |
|
Here's my report :) PR #45 Benchmark ReportGPU: AMD Radeon RX 9060 XT (ROCm, gfx1200), 16GB VRAM Model under test:
Bench settings used:
1) Q8_0 baseline2) Config I (TQ4_1S)3) Config I + TurboQuant KV (
|
|
Good catch @swfsql. I verified this on Qwen3.5-27B-Q8_0. The layer pattern is a 1:3 interleave — only 16 of 64 layers are self-attention with split With boundary=2, blk.0-1 are protected but those are delta net layers — no split attention tensors to protect. The first real self-attention layer (blk.3) is unprotected. The fused I tested boundary=2 vs boundary=4 on M5 Max to measure the impact:
boundary=4 protects blk.3 (first real self-attention) and gives a 0.3% PPL improvement at the cost of 500 MiB. Real but small. The delta net layers are accidentally safe — their fused For the default Config I recommendation, I am keeping boundary=2 since the practical difference is marginal. But this is useful context for anyone tuning Qwen 3.5 specifically — boundary=4 is a free 0.3% if you can spare the 500 MiB. Re: compressing the fused |
- turbo4 K+V results on Qwen3.5-27B (-0.32% vs q8_0) and Qwen3-14B (+6.3%) - Sparse V dequant benchmarks: MoE native dequant +10.9% at 8K - Gemma-3 turbo3 results post-iSWA fix (+3.3%) - KVLinC no-K-rotation negative result - Speculative decoding negative result - CUDA 13.2 compatibility verified - Experiments #31, #39, #42, #45, #49, #50, #51 status updates Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
I guess you're done here anyway, yet wanting to let you know that the compressing as described in Getting started seems to either miss something or isn't very clear, at least in my case I wasn't able to replicate the "Quick Test" as the output model (Qwen 3.5 35b) always turned out nearly the same size with config_i except for a few MBs. Or do I need to change the config_i for the 35b model somewhat? str: cannot properly format tensor name position_embd with suffix=weight bid=-1 xid=-1 |
|
thank you for the continued benchmarks! |
Good catch. Qwen3.5-35B is a hybrid model — only 16 of 64 layers have split attn_q/attn_k/attn_v tensors (blk.3, 7, 11, 15, ..., 63). The other 48 are Gated Delta Net layers with fused You need to adjust Compressing fused |
turbo4 SET_ROWS was using turbo3's shared template with wrong 2+1 bit packing. New dedicated kernel_set_rows_turbo4 with correct 3-bit packed indices + QJL signs. PPL: 679 → 6.19. Also added turbo4 prefill FA kernel instantiations (non-vec path). QJL ablation finding: disabling QJL improves PPL from 6.1894 to 6.1756 (identical to turbo3). QJL correction hurts quality in attention context. Consistent with scos-lab issue TheTom#45. Co-Authored-By: tturney@psyguard.ai Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
turbo4 SET_ROWS was using turbo3's shared template with wrong 2+1 bit packing. New dedicated kernel_set_rows_turbo4 with correct 3-bit packed indices + QJL signs. PPL: 679 → 6.19. Also added turbo4 prefill FA kernel instantiations (non-vec path). QJL ablation finding: disabling QJL improves PPL from 6.1894 to 6.1756 (identical to turbo3). QJL correction hurts quality in attention context. Consistent with scos-lab issue TheTom#45. Co-Authored-By: tturney@psyguard.ai Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
turbo4 SET_ROWS was using turbo3's shared template with wrong 2+1 bit packing. New dedicated kernel_set_rows_turbo4 with correct 3-bit packed indices + QJL signs. PPL: 679 → 6.19. Also added turbo4 prefill FA kernel instantiations (non-vec path). QJL ablation finding: disabling QJL improves PPL from 6.1894 to 6.1756 (identical to turbo3). QJL correction hurts quality in attention context. Consistent with scos-lab issue TheTom#45. Co-Authored-By: tturney@psyguard.ai Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
I'm working on a vulkan port of this. PR soon |
turbo4 SET_ROWS was using turbo3's shared template with wrong 2+1 bit packing. New dedicated kernel_set_rows_turbo4 with correct 3-bit packed indices + QJL signs. PPL: 679 → 6.19. Also added turbo4 prefill FA kernel instantiations (non-vec path). QJL ablation finding: disabling QJL improves PPL from 6.1894 to 6.1756 (identical to turbo3). QJL correction hurts quality in attention context. Consistent with scos-lab issue TheTom#45. Co-Authored-By: tturney@psyguard.ai Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
turbo4 SET_ROWS was using turbo3's shared template with wrong 2+1 bit packing. New dedicated kernel_set_rows_turbo4 with correct 3-bit packed indices + QJL signs. PPL: 679 → 6.19. Also added turbo4 prefill FA kernel instantiations (non-vec path). QJL ablation finding: disabling QJL improves PPL from 6.1894 to 6.1756 (identical to turbo3). QJL correction hurts quality in attention context. Consistent with scos-lab issue TheTom#45. Co-Authored-By: tturney@psyguard.ai Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
turbo4 SET_ROWS was using turbo3's shared template with wrong 2+1 bit packing. New dedicated kernel_set_rows_turbo4 with correct 3-bit packed indices + QJL signs. PPL: 679 → 6.19. Also added turbo4 prefill FA kernel instantiations (non-vec path). QJL ablation finding: disabling QJL improves PPL from 6.1894 to 6.1756 (identical to turbo3). QJL correction hurts quality in attention context. Consistent with scos-lab issue TheTom#45. Co-Authored-By: tturney@psyguard.ai Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
turbo4 SET_ROWS was using turbo3's shared template with wrong 2+1 bit packing. New dedicated kernel_set_rows_turbo4 with correct 3-bit packed indices + QJL signs. PPL: 679 → 6.19. Also added turbo4 prefill FA kernel instantiations (non-vec path). QJL ablation finding: disabling QJL improves PPL from 6.1894 to 6.1756 (identical to turbo3). QJL correction hurts quality in attention context. Consistent with scos-lab issue #45. Co-Authored-By: tturney@psyguard.ai Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
turbo4 SET_ROWS was using turbo3's shared template with wrong 2+1 bit packing. New dedicated kernel_set_rows_turbo4 with correct 3-bit packed indices + QJL signs. PPL: 679 → 6.19. Also added turbo4 prefill FA kernel instantiations (non-vec path). QJL ablation finding: disabling QJL improves PPL from 6.1894 to 6.1756 (identical to turbo3). QJL correction hurts quality in attention context. Consistent with scos-lab issue TheTom#45. Co-Authored-By: tturney@psyguard.ai Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
turbo4 SET_ROWS was using turbo3's shared template with wrong 2+1 bit packing. New dedicated kernel_set_rows_turbo4 with correct 3-bit packed indices + QJL signs. PPL: 679 → 6.19. Also added turbo4 prefill FA kernel instantiations (non-vec path). QJL ablation finding: disabling QJL improves PPL from 6.1894 to 6.1756 (identical to turbo3). QJL correction hurts quality in attention context. Consistent with scos-lab issue TheTom#45. Co-Authored-By: tturney@psyguard.ai Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
turbo4 SET_ROWS was using turbo3's shared template with wrong 2+1 bit packing. New dedicated kernel_set_rows_turbo4 with correct 3-bit packed indices + QJL signs. PPL: 679 → 6.19. Also added turbo4 prefill FA kernel instantiations (non-vec path). QJL ablation finding: disabling QJL improves PPL from 6.1894 to 6.1756 (identical to turbo3). QJL correction hurts quality in attention context. Consistent with scos-lab issue TheTom#45. Co-Authored-By: tturney@psyguard.ai Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
turbo4 SET_ROWS was using turbo3's shared template with wrong 2+1 bit packing. New dedicated kernel_set_rows_turbo4 with correct 3-bit packed indices + QJL signs. PPL: 679 → 6.19. Also added turbo4 prefill FA kernel instantiations (non-vec path). QJL ablation finding: disabling QJL improves PPL from 6.1894 to 6.1756 (identical to turbo3). QJL correction hurts quality in attention context. Consistent with scos-lab issue TheTom#45. Co-Authored-By: tturney@psyguard.ai Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
turbo4 SET_ROWS was using turbo3's shared template with wrong 2+1 bit packing. New dedicated kernel_set_rows_turbo4 with correct 3-bit packed indices + QJL signs. PPL: 679 → 6.19. Also added turbo4 prefill FA kernel instantiations (non-vec path). QJL ablation finding: disabling QJL improves PPL from 6.1894 to 6.1756 (identical to turbo3). QJL correction hurts quality in attention context. Consistent with scos-lab issue TheTom#45. Co-Authored-By: tturney@psyguard.ai Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
turbo4 SET_ROWS was using turbo3's shared template with wrong 2+1 bit packing. New dedicated kernel_set_rows_turbo4 with correct 3-bit packed indices + QJL signs. PPL: 679 → 6.19. Also added turbo4 prefill FA kernel instantiations (non-vec path). QJL ablation finding: disabling QJL improves PPL from 6.1894 to 6.1756 (identical to turbo3). QJL correction hurts quality in attention context. Consistent with scos-lab issue TheTom#45. Co-Authored-By: tturney@psyguard.ai Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
turbo4 SET_ROWS was using turbo3's shared template with wrong 2+1 bit packing. New dedicated kernel_set_rows_turbo4 with correct 3-bit packed indices + QJL signs. PPL: 679 → 6.19. Also added turbo4 prefill FA kernel instantiations (non-vec path). QJL ablation finding: disabling QJL improves PPL from 6.1894 to 6.1756 (identical to turbo3). QJL correction hurts quality in attention context. Consistent with scos-lab issue TheTom#45. Co-Authored-By: tturney@psyguard.ai Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
turbo4 SET_ROWS was using turbo3's shared template with wrong 2+1 bit packing. New dedicated kernel_set_rows_turbo4 with correct 3-bit packed indices + QJL signs. PPL: 679 → 6.19. Also added turbo4 prefill FA kernel instantiations (non-vec path). QJL ablation finding: disabling QJL improves PPL from 6.1894 to 6.1756 (identical to turbo3). QJL correction hurts quality in attention context. Consistent with scos-lab issue TheTom#45. Co-Authored-By: tturney@psyguard.ai Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
turbo4 SET_ROWS was using turbo3's shared template with wrong 2+1 bit packing. New dedicated kernel_set_rows_turbo4 with correct 3-bit packed indices + QJL signs. PPL: 679 → 6.19. Also added turbo4 prefill FA kernel instantiations (non-vec path). QJL ablation finding: disabling QJL improves PPL from 6.1894 to 6.1756 (identical to turbo3). QJL correction hurts quality in attention context. Consistent with scos-lab issue TheTom#45. Co-Authored-By: tturney@psyguard.ai Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…026-07-12) 4 parallele Subagents (Vulkan/AMD, CUDA/MoE, arXiv, Multi-GPU/Batching) konsolidiert zu 25 neuen Items in ROADMAP: Tier 1 Quick Wins (3 neu): - AtomicBot-ai#31 K-Quant A-Matrix Transpose CM1 (PR ggml-org#22970, +5-15% PP auf Mars) - AtomicBot-ai#32 Pascal L1 Cache Tuning (-Xptxas -dlcm=ca, Styx) - TheTom#33 Per-Quant MMVQ/MMQ Batch Threshold (AMD MFMA, Mars/Venus) Tier 2 (7 neu): - TheTom#34 UBBoost, TheTom#35 Row-Packing DMMV, TheTom#36 Auto Param Fitting TP - TheTom#37 LFRU Expert Caching, TheTom#38 Conf-KV, TheTom#39 Talon, TheTom#40 MoE Load Balancing Tier 3 (5 neu): - TheTom#41 GRKV, TheTom#42 CapKV, TheTom#43 SliderQuant, TheTom#44 Alloc-MoE, TheTom#45 CUDA Streams QKV Tier 4 (10 neu): - TheTom#46-55: SpecMD, QUICK, FluxMoE, STAR-KV, VQKV, CompilerKV, SliceMoE, MoBiE, DASH-Q, GOOSE 7 PRs als bereits im Fork identifiziert (nicht erneut vorschlagen): ggml-org#21472, ggml-org#23764, ggml-org#22299, ggml-org#21611, ggml-org#22423, ggml-org#18749, Warp Shuffle, Constant Memory
Pre-Solo Planung nach solo-session Skill Methodik: - Phase 1: E4B+MTP 8GB Crash untersuchen (~3-4h) - Phase 2: TheTom#35 Row-Packing DMMV implementieren (~4-6h) - Phase 3: Batch-Evaluation 8 Tier 2 Items (~3-4h) - Phase 4: TheTom#45 CUDA Streams QKV Prototyp (~2-3h) Entscheidungen: - Uranus ist online → E4B auf 16GB testbar - Services deaktivieren für Tests, später reaktivieren - Code-Review Pflicht bei nicht-trivialen Änderungen - Kein Abbruch zwischendrin
…DA Graphs Feature ist vollständig implementiert (PR ggml-org#16991, GGML_CUDA_GRAPH_OPT=1). Benchmark auf Uranus (RTX 4060 Ti, E4B Q4_K_XL): - Mit CUDA Graphs: tg2048 71.50→63.82 t/s (-10.7%, ±18.77 Varianz) → interleaved Node-Order bricht Graph-Capture-Effizienz - Ohne CUDA Graphs: tg512 72.24→72.99 (+1%, im Rauschen) → QKV-Projektionen zu klein bei E4B für nennenswerten Overlap ROADMAP TheTom#45 auf ❌ gesetzt.
…ffload blockiert CUDA Graphs)
Summary
simd_shuffle_xor, NR0=8llama-quantize --allow-requantize --tensor-type-file config.txtTested Models
Llama Note
Llama-family models show 6-8x higher per-layer error amplification with WHT-rotated FFN tensors. Use Hybrid (TQ4 attn + Q4_K FFN) or Premium (TQ4 attn + Q5_K/Q6_K FFN) configs. Both beat Q4_K_M in quality and speed at similar size. Full investigation in the paper.
What's needed before merge
Metal only
The quantization step (
llama-quantize) works on any platform. The runtime dequant kernels are Metal-specific. Compressed GGUFs will not run correctly on CUDA/HIP until those backends are ported.Paper: https://github.com/TheTom/turboquant_plus/blob/main/docs/papers/weight-compression-tq4.md
Getting started: https://github.com/TheTom/turboquant_plus/blob/main/docs/getting-started.md
🤖 Generated with Claude Code