(close due to violation AI policy) vulkan: add TQ3_0 (TurboQuant) 3.5-bit KV cache quantization#21010
Conversation
Add TurboQuant 3.5-bit KV cache type (TQ3_0) with 14-byte block: 8B codebook indices + 4B QJL residual signs + 2B fp16 scale. Block size 32, enum value 41, type_traits with to_float/from_float_ref. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implement Walsh-Hadamard Transform (order-32) with sign preconditioning and 4-level codebook quantization for TQ3_0. Includes forward WHT for quantize, inverse WHT for dequantize, CPU wrapper, type_traits_cpu entry, and ops.cpp switch-case registration for all quantized-type ops. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add GGML_TYPE_TQ3_0 to kv_cache_types vector so --cache-type-k tq3_0 and --cache-type-v tq3_0 are accepted by llama-server and llama-cli. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add Vulkan shader support for TQ3_0 (3.5-bit TurboQuant) KV cache type: - types.glsl: block_tq3_0 struct (8B qs + 4B qr + 2B gamma = 14 bytes/32 elements) with packed16 variant for flash attention access - copy_to_quant.comp: GPU quantizer with WHT forward transform (signs → butterflies → normalize), 4-level codebook quantization, and QJL residual signs - dequant_funcs.glsl: Unscaled dequant for mul_mat path (caller applies gamma via get_dm), WHT inverse (butterflies → normalize+signs), plus get_dm returning gamma - flash_attn_base.glsl: Fully-scaled dequant for flash attention path (FA doesn't call get_dm), reads from packed16 buffers via binding_idx - dequant_tq3_0.comp: Standalone dequant shader for get_rows and similar ops Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…stration Register TQ3_0 (TurboQuant 3.5-bit) in the Vulkan build system and runtime so the previously-committed GLSL shaders are compiled to SPIR-V and available as GPU pipelines. Build system (vulkan-shaders-gen.cpp): - Add "tq3_0" to type_names vector for dequant/get_rows/mul_mat_vec - Add to flash_attn scalar and coopmat1 shader generation conditions - Add to copy_to_quant/copy_from_quant shader compilation loops - Add to set_rows shader compilation loop Runtime (ggml-vulkan.cpp): - Register pipeline_dequant[GGML_TYPE_TQ3_0] - Register pipeline_cpy_f32_quant and pipeline_cpy_quant_f32 for TQ3_0 - Register pipeline_set_rows for TQ3_0 (i32 and i64 index types) - Register CREATE_FA for scalar path (fp16 and fp32 accumulator) - Register CREATE_FA for coopmat1 path - Add GGML_TYPE_TQ3_0 to ggml_vk_supports_op for FLASH_ATTN_EXT, SET_ROWS, CPY/DUP/CONT operations - Add to ggml_vk_get_cpy_pipeline dispatch switches Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Hi @crayolaconsumer, thanks for your contribution! Per our contribution guidelines, the automated PR checker found the following issue(s) that need your attention:
Please note that maintainers reserve the right to make final decisions on PRs. If you believe there is a mistake, please comment below. |
|
Interesting work! A few technical observations:
This uses all 3 bits for reconstruction with theoretical MSE of ~0.0346 for N(0,1). Without the QJL correction path actually implemented, the 4-level codebook gives substantially worse distortion for the same 14-byte block. The
I have a CPU-only implementation with the 8-level codebook + vec_dot on my fork (branch If you'll use the 8-level codebook or da vec_dot implementation, feel free to cherry pick from |
|
Thank you for the pointer! i'm very new to this, just chasing what i find but your comment has made a big improvement! i'll outline that AI helped me create this in another PR, fingers crossed! |
|
i can't build it there is more and anything that has tq3_0 in it fails here, |
Summary
Adds
GGML_TYPE_TQ3_0— a 3.5-bit KV cache quantization type based on Google's TurboQuant algorithm (arXiv:2504.19874, ICLR 2026). Provides ~4.6x KV cache compression vs FP16 with near-zero quality loss.Tested on: AMD Radeon RX 7800 XT (RDNA3, Vulkan backend) with Qwen 3.5 27B (hybrid DeltaNet+Attention architecture).
Results
Algorithm
TurboQuant uses a 32-element Walsh-Hadamard Transform (WHT) rotation to gaussianize input vectors, then applies a 2-bit Max-Lloyd codebook quantization + 1-bit QJL residual sign:
Block format: 14 bytes per 32 elements (3.5 bits/value)
qs[8]— 32 × 2-bit codebook indicesqr[4]— 32 × 1-bit QJL residual signs (stored, not used in MSE-only reconstruction)gamma— FP16 per-block scaleWHT Forward (quantize): sign preconditioning → 5 butterfly stages → normalize
WHT Inverse (dequantize): 5 butterfly stages → normalize + undo signs
Codebook: Max-Lloyd optimal 4-level for N(0,1): {-1.510, -0.4528, +0.4528, +1.510}
The WHT is self-inverse and operates in-register (no shared memory needed for the per-block quantize/dequant path).
Changes
GGML core:
ggml.h—GGML_TYPE_TQ3_0 = 41enum, incrementGGML_TYPE_COUNTggml-common.h—block_tq3_0struct (14 bytes),QK_TQ3_0 = 32ggml.c—type_traitsentryggml-quants.{h,c}— CPU reference quantize/dequantize with WHT rotationggml-cpu/{ggml-cpu.c,quants.{h,c},ops.cpp}— CPU backend wrappersVulkan backend:
types.glsl— block struct + packed16 for flash attentioncopy_to_quant.comp— GPU quantizer (single-threaded WHT + codebook per block)dequant_funcs.glsl— unscaled dequant for mul_mat path +get_dm()flash_attn_base.glsl— scaled dequant for flash attention inner loopdequant_tq3_0.comp— standalone dequant shadervulkan-shaders-gen.cpp— shader compilation registration (FA, cpy, set_rows)ggml-vulkan.cpp— pipeline registration, FA allowlist, supports_opCLI:
arg.cpp—tq3_0added tokv_cache_typesallowlistUsage
Flash attention is required (KV cache quantization depends on FA).
References
Known Limitations
qrbits) is stored but not used in the dequant path — MSE-only reconstruction. A fused MMVQ kernel could use the QJL bits for unbiased inner product estimation (future work).dequant_funcs.glsluses Approach A (full 32-element WHT per thread in registers). Cooperative shared-memory WHT would be more efficient but requires calling convention changes.Testing
cmake --buildpasses with zero errorsllama-server --helpshowstq3_0in cache type options--cache-type-k tq3_0 --cache-type-v tq3_0