onur-gokyildiz-bhi/tq-kv

Pure Rust implementation of Google's TurboQuant (ICLR 2026) — KV cache compression for LLMs

Rust

37

396 commits

updated Apr 19, 2026

See the code

README

tq-kv

Pure Rust TurboQuant KV cache compression. CUDA. AVX2 SIMD. C FFI. crates.io.

Crates.io License Tests CUDA no_std

Implementation of Google's TurboQuant (ICLR 2026) with the 3-Fix framework that enables aggressive key compression (4-bit, 7.5x) on GGUF quantized models -- where symmetric K compression produces catastrophic output.

Now with Pre-RoPE key quantization (34-59% less PPL gap), KV Compaction (up to 25x token reduction), TriAttention eviction for constant-memory KV cache, per-token mean removal (+40% attention quality at 2-bit), and multi-arch CUDA (Turing → Hopper).

tq-engine Web UI demo — Qwen2.5 7B with TurboQuant 4-bit KV compression


Current performance

RTX 3080 10 GB, Qwen2.5-7B-Instruct Q4_K_M, own CUDA kernels, no external inference dependency. Three-run mean at 2026-04-19, warmup discarded, TTFT separated.

Modetok/sTTFTPPL (/tmp/ppl_bench.txt)KV memory
Standard63.60.19 s11.508grows linearly
TQ 4-bit39.30.11 s12.473 (+8.4%)3.8× smaller
TQ 4-bit + TriAttention37.60.11 s12.473 (+8.4%)constant
  • llama.cpp head-to-head gap narrowed from 4.0× at v0.6.0 to 1.83× at v0.7.0.
  • A pre-push hook enforces PPL thresholds (Std ≤ 12.66, TQ ≤ 13.72) on every kernel change.
  • Known limit on 10 GB cards: prefill attention is O(N²), so the CLI OOMs past ~2 K prompt length regardless of KV compression. See scripts/bench-long-context.sh for the forcing measurement.

Full matrix (Llama 3.1 8B, Mistral 7B, multi-context, reproducible CLIs): BENCHMARKS.md.

What's next (v0.8.0)

Everything below is gated and unscoped; priorities in order:

  • Megakernel wiring. v0.7.0 ships the 6-phase persistent kernel with all stubs promoted to real bodies and the >48 KB shmem opt-in; the last mile is routing TQ_MEGAKERNEL=1 through model.rs::forward. Architect projection +~10 %; will be measured, not claimed, at merge.
  • Flash-attention for PREFILL. We only have flash_decode (single-token). Prefill attention's N×N score tensor is the real long-context OOM cliff; a flash-prefill port unlocks ≥ 4 K contexts on 10 GB cards.
  • EAGLE acceptance debug. Sprint 1–3 shipped the draft loader, tree attention, and acceptance probe in v0.7.0. The draft forward is bit-correct against a numpy reference but acceptance sits at ~6.7 % — a torch-based reference covering non-zero inputs is the likely unlock. Week-scale.
  • Metal backend kickoff (blocked on a collaborator with Apple Silicon).

Full plan: see the status:planned nodes in the project knowledge graph.


The Compound Error Problem

GGUF quantized models (Q4_K_M) already have weight quantization noise. Compressing KV cache on top introduces compound error through softmax. tq-kv solves this with a multi-stage pipeline:

ConfigQwen 7B Q4_K_M PPLStatus
No compression4.136Baseline
tq-kv 4-bit4.457 (+8%)Production
tq-kv 4-bit + TriAttention4.574 (+11%)Constant memory
tq-kv 4-bit (no calibration)~15+Needs auto-calibrate

Key innovations for GGUF compound error:

  • 3-Fix framework: sink tokens (FP16), current token (lossless POQ), cache reset
  • Pre-RoPE quantization: position-independent per-channel stats, better codebook fit
  • Per-token mean removal: softmax shift-invariance exploited, +40% attention quality at 2-bit
  • Auto-calibration: zero-config — calibrates on first use (256 samples, 2-3 seconds)

Measured Quality (Honest Numbers)

All PPL measured with automated tq perplexity / tq ablate.

GGUF Q4_K_M Models (compound error)

Qwen 2.5 7B Q4_K_M, modern English, skip=4, sink=4

ConfigPPLvs BaselineCompression
Baseline (no TQ)1.823--1x
Pre-RoPE 4-bit1.890+3.7%~7.5x
Standard 4-bit1.925+5.6%~7.5x
TQ + Compact (500t/30%)2.227+22.2%~25x
Pre-RoPE + Compact (500t/30%)2.281+25.1%~25x
Full stack (Pre-RoPE+V4+Compact)2.84+55.8%~100x

Pre-RoPE Improvement Across Context Lengths

TokensBaselineStandard TQ (delta)Pre-RoPE (delta)Gap Reduction
4755.1175.820 (+13.7%)5.403 (+5.6%)59%
7934.9015.250 (+7.1%)5.125 (+4.6%)35%
21061.8231.925 (+5.6%)1.890 (+3.7%)34%

Value Compression is Nearly Free

Value ConfigExtra PPL vs K-onlyValue Savings
V-fp16 (default)--1.0x
V-8bit (TQ_VBITS=8)+0.2%2.0x
V-4bit (TQ_VBITS=4)+1.3%3.2x

FP16 Models (no compound error)

Qwen 2.5 0.5B FP16 safetensors, wikitext-2

BitsPPLvs BaselineCompression
Baseline10.740--1.0x
4-bit11.967+11.4%7.5x
2-bit27.696+157.9%14.2x

Compression Quality (per-layer)

ModelBitsRatioSNR (dB)Cosine Sim
Llama-3 8B214.2x9.20.943
Llama-3 8B47.5x20.40.996
Gemma 3 4B215.1x9.20.943

NIAH (Needle-In-A-Haystack)

Bit Width10%25%50%75%90%
4-bitPASSPASSPASSPASSPASS
2-bitPASSPASSPASSPASSPASS

Quick Start

Install

[dependencies]
tq-kv = "0.6"

CLI (tq-engine)

# Pull a model
tq pull qwen2:7b

# Chat with TurboQuant compression
tq chat qwen2:7b --turbo-quant

# Chat with Pre-RoPE (best quality)
TQ_PRE_ROPE=1 tq chat qwen2:7b --turbo-quant

# Start OpenAI-compatible API server
tq serve --model qwen2:7b --turbo-quant --port 11435

# Evaluate perplexity
tq perplexity --model qwen2:7b eval.txt --turbo-quant

# Calibrate (optimal codebook + rotation from real activations)
tq calibrate qwen2:7b --text calibration_data.txt

# Run ablation study
tq ablate qwen2:7b --file eval.txt --quick --output results.csv

Library API

use tq_kv::*;

let config = TurboQuantConfig::balanced(); // 4-bit, 7.5x compression
let dim = 128;

// Batch compress
let compressed = compress_keys(&kv_data, dim, &config);
println!("Ratio: {:.1}x", compressed.compression_ratio());

// Fused attention -- no decompression, AVX2+FMA SIMD
let signs = hadamard::generate_signs(dim, config.rotation_seed);
let centroids = codebook::get_centroids(config.bits);
let rotated_q = pre_rotate_query_with_signs(&query, &signs);
let scores = fused_attention_scores(&rotated_q, &compressed, centroids, scale);

// KV Compaction -- reduce token count
let compacted = compaction::compact_head(&keys, &values, &queries,
    seq_len, n_queries, dim, target_size);
// compacted.keys, compacted.beta, compacted.values

How It Works

Input KV vector (from GGUF Q4_K_M model)
    |
[0] Pre-RoPE capture (optional)            O(1)
    |  Compress BEFORE RoPE for position-independent stats
    |
[1] Channel bias subtraction (calibrated)   O(d)
    |  Remove weight-quantization artifacts
    |
[2] Per-token mean removal                   O(d)
    |  Softmax shift-invariant: attention ignores mean
    |  Frees codebook precision (+40% cosine sim @ 2-bit)
    |
[3] Randomized Hadamard Transform            O(d log d)
    |  Decorrelates outliers -> coordinates ~ Gaussian
    |
[4] Per-channel adaptive sigma (KIVI-style)  O(d)
    |  Per-dimension variance from calibration
    |  Lloyd-Max codebook + norm correction
    |
[5] SRHT QJL Error Correction (optional)     O(d log d)
    |  Structured Hadamard projection (+4.5 dB SNR)
    |
Output: packed indices + corrected norm + mean
        7.5x compression at 4-bit (keys only)

3-Fix for GGUF Models

Fix 1: Sink tokens (first 4) stay FP16     -> -81% attention error
Fix 2: Current token = lossless (POQ)       -> highest-impact position protected
Fix 3: Cache reset per conversation         -> prevents cross-contamination

6-Segment Attention

[sink FP16] [cold decayed] [compacted + beta] [hot compressed] [current FP16]
     |            |                |                   |                |
  Always       Temporal        Attention-           Per-head          POQ
  lossless     decay           matching             adaptive         lossless
  (Fix 1)                      reduction            bitwidth         (Fix 2)
                                    ^
                              TriAttention eviction scores all segments,
                              keeps top-B tokens, maintains fixed budget

TriAttention: Constant-Memory KV Cache

Based on TriAttention (Mao et al., 2026). Pre-RoPE Q/K vectors concentrate around fixed centers, enabling cheap trigonometric importance scoring without full attention computation.

Orthogonal to TurboQuant: TriAttention decides which tokens to keep (eviction), TurboQuant decides how to compress them (quantization). Combined: fixed-size KV cache at any context length.

# TQ+TriAttention is ON by default with --turbo-quant (requires calibration)
tq chat qwen2:7b --turbo-quant

# Disable TriAttention (TQ-only mode)
TQ_TRIATTN=0 tq chat qwen2:7b --turbo-quant

# Custom budget
TQ_TRIATTN_BUDGET=256 tq chat qwen2:7b --turbo-quant

Memory Projection (Qwen2.5-7B, TQ 4-bit + TriAttention, budget=128)

Context LengthFP16 KVTQ 4-bitTQ + TriAttnTotal Compression
4K tokens235 MB154 MB4.8 MB49x
32K tokens1,879 MB1,233 MB4.8 MB390x
128K tokens7,516 MB4,933 MB4.8 MB1,560x

Speed vs Budget (RTX 3080, Qwen2.5-7B, 100 tokens)

Budgettok/svs TQ onlyFixed KV Memory
51215.3-6%19.3 MB
25615.3-6%9.6 MB
12813.8-15%4.8 MB
647.9-46%2.4 MB
(none)16.2--grows linearly

What Fits in 10GB VRAM (5GB available for KV cache)

MethodMax Context Length
FP16 KV~87,000 tokens
TQ 4-bit~133,000 tokens
TQ + TriAttentionunlimited

Configuration Guide

Use CaseKey ConfigPPL ImpactCompression
Best qualityTQ_PRE_ROPE=1+3.7%~7.5x
Balanced--turbo-quant (default)+5.6%~7.5x
Maximum savingsTQ_PRE_ROPE=1 TQ_VBITS=4+5.0%~24x
Long contextTQ_PRE_ROPE=1 TQ_COMPACT=1000 TQ_COMPACT_RATIO=30+30%~50x
ExtremePre-RoPE + V4 + Compact+56%~100x
Unlimited contextTQ_TRIATTN=1 TQ_TRIATTN_BUDGET=256TBDconstant 10 MB

Environment Variables

VariableDefaultDescription
TQ_SKIP4Initial layers kept uncompressed (fp16 KV)
TQ_PROTECT_LAST0Final layers kept uncompressed (boundary protection)
TQ_SINK4Initial tokens preserved at fp16 (attention sinks)
TQ_PRE_ROPE0Pre-RoPE key quantization (1=enabled, best quality)
TQ_COMPACT0Compaction threshold (0=off, e.g. 500=compact when >500 hot tokens)
TQ_COMPACT_RATIO5Compaction target (% of original tokens to keep)
TQ_VBITS0Value compression bits (0=fp16, 4=4-bit, 8=8-bit)
TQ_SPARSE_V1e-6Skip V rows where softmax weight < threshold
TQ_FUSED0Fused attention from compressed indices (CPU only)
TQ_DECAYoffTemporal decay (format: "age:bits" e.g. "512:2")
TQ_LAYER_BITS--Per-layer bit width (format: "start-end:bits")
TQ_HEAD_BITS--Per-head bit width (format: "0-3:4,4-7:2")
TQ_GROUP32Group size for per-group sigma
TQ_BIAS_CORRECT0Softmax bias correction (experimental)
TQ_NO_CAL0Disable calibration auto-loading
TQ_TRIATTNonTriAttention eviction (on by default with --turbo-quant, 0=disable)
TQ_TRIATTN_BUDGET2048Max KV tokens to retain (lower = more aggressive eviction, e.g. 128/256/512)
TQ_TRIATTN_INTERVAL128Eviction check interval in tokens
TQ_CENTER_KEYS1Per-token mean removal (softmax shift-invariant, +40% @ 2-bit)
TQ_MAX_SEQ2048Maximum KV cache sequence length
TQ_NO_PER_CHANNEL0Disable per-channel sigma (KIVI-style, for A/B testing)
TQ_CUDA_ARCHESallCUDA target arches (e.g. "86" for dev, "75,80,86,89,90" for release)

VRAM Savings

ModelContextFP16 KVTQ 4-bitTQ 2-bitSavings
Qwen 2.5 7B4K256 MB34 MB18 MB7.5-14.2x
Qwen 2.5 72B4K640 MB85 MB45 MB7.5-14.2x
Llama 3.1 70B32K20 GB2.7 GB1.4 GB7.5-14.2x

With KV Compaction: effective compression reaches 100-400x. With TriAttention: constant-memory KV cache -- up to 1,560x at 128K context.


SRHT QJL Performance (32K vectors, d=128, release)

MetricDense QJL (paper)SRHT QJL (ours)No QJL
Compress overhead29x1.45x1.0x
SNR improvement+1.2 dB+4.5 dB--
Attention KL div.--2.9x lower--

Full Product: tq-engine

tq-kv powers tq-engine -- "Rust's Ollama" with TurboQuant compression:

tq pull qwen2:7b          # download from HuggingFace
tq serve --turbo-quant     # OpenAI-compatible API (SSE streaming)
tq chat qwen2:7b           # terminal chat

Web UI at localhost:11435. Works with ChatBox and Open WebUI.

4 validated models: Qwen2.5 7B/0.5B, Llama 3.1 8B, Mistral 7B. Auto-detected from GGUF metadata.

3-Way Benchmark

tq bench qwen2:7b                    # Standard vs TQ vs TQ+TriAttention
tq perplexity -m qwen2:7b --compare eval.txt  # 3-way PPL comparison
scripts/ppl-check.sh                  # Regression CI (9 checks, tight thresholds)

GPU Inference Performance

RTX 3080 10GB, Qwen 2.5 7B Q4_K_M, own CUDA kernels (no candle dependency). Full reproducible matrix in BENCHMARKS.md.

Modetok/sTTFTPPLKV Memory
Standard28.00.19s4.136grows linearly
TQ 4-bit19.70.10s4.457 (+7.8%)3.8x smaller
TQ+TriAttention19.40.11s4.574 (+10.6%)constant

4 validated models: Qwen2.5 7B/0.5B, Llama 3.1 8B, Mistral 7B. Auto-calibration on first use.

Custom CUDA Kernel Stack (78 kernels, 16 files, 4.4K lines)

  • Multi-arch: sm_75 (Turing) → sm_90 (Hopper), runtime GPU detect, per-arch PTX
  • Butterfly reduce: __shfl_xor_sync broadcast to all threads (no broadcast hacks)
  • cp.async pipeline: double-buffered qmatmul on Ampere+ (sm_80+), sync fallback on Turing
  • Fused layer kernels: RmsNorm + Q4K QKV + bias, gateup + SiLU, down + residual
  • Q4K/Q6K/Q8_0 fused matvec: __ldg read-only cache, dequant + dot in single kernel
  • Flash decode v2: split-KV parallelism for long context (>256 tokens), online softmax
  • TQ fused attention: compressed KV → attention score without decompression (moat kernel)
  • CUDA Graph replay: short context (<256) as single GPU operation, auto-fallback to eager mode

Optimization History

Phasetok/sKey Change
Baseline (candle)1.3candle framework
Custom CUDA kernels1.9Own matvec, RoPE, attention
DecodeScratch + fused10.1Zero-alloc decode, fused kernels
GPU prefill + CUDA Graph17.8Graph replay, Q6K lm_head
v2 kernels + multi-arch18.5__ldg, warp-reduce, cp.async, butterfly reduce
cp.async weight pipeline23.3MLP gateup + MLP down + qmatmul cp.async W-prefetch
mrow ladder (v0.6, shipped 2026-04-14)28.0cooperative-per-superblock gateup/down, RoPE Q+K fuse, bias-fused LM head

Benchmark

cargo run --release -p tq-kv --bin tq-kv-bench

Full results: BENCHMARK.md

Paper

Our work:

  • "TurboQuant on Quantized Models: Solving Compound Quantization Error with Pre-RoPE Compression and KV Compaction" -- BHI Research (2026)
  • 3-Fix framework, SRHT QJL (115x speedup), Pre-RoPE quantization, KV Compaction, Adaptive QJL

Original:

  • Zandieh, Daliri, Hadian, Mirrokni. "TurboQuant: Online Vector Quantization with Near-optimal Distortion Rate." ICLR 2026. arXiv:2504.19874
  • Mao, Lin, Huang et al. "TriAttention: Efficient Long Reasoning with Trigonometric KV Compression." 2026. arXiv:2604.04921

License

MIT OR Apache-2.0

Contributors

onur-gokyildiz-bhi/tq-kv

Pure Rust implementation of Google's TurboQuant (ICLR 2026) — KV cache compression for LLMs

Rust

37

396 commits

updated Apr 19, 2026

See the code

README

tq-kv

Pure Rust TurboQuant KV cache compression. CUDA. AVX2 SIMD. C FFI. crates.io.

Crates.io License Tests CUDA no_std

Implementation of Google's TurboQuant (ICLR 2026) with the 3-Fix framework that enables aggressive key compression (4-bit, 7.5x) on GGUF quantized models -- where symmetric K compression produces catastrophic output.

Now with Pre-RoPE key quantization (34-59% less PPL gap), KV Compaction (up to 25x token reduction), TriAttention eviction for constant-memory KV cache, per-token mean removal (+40% attention quality at 2-bit), and multi-arch CUDA (Turing → Hopper).

tq-engine Web UI demo — Qwen2.5 7B with TurboQuant 4-bit KV compression


Current performance

RTX 3080 10 GB, Qwen2.5-7B-Instruct Q4_K_M, own CUDA kernels, no external inference dependency. Three-run mean at 2026-04-19, warmup discarded, TTFT separated.

Modetok/sTTFTPPL (/tmp/ppl_bench.txt)KV memory
Standard63.60.19 s11.508grows linearly
TQ 4-bit39.30.11 s12.473 (+8.4%)3.8× smaller
TQ 4-bit + TriAttention37.60.11 s12.473 (+8.4%)constant
  • llama.cpp head-to-head gap narrowed from 4.0× at v0.6.0 to 1.83× at v0.7.0.
  • A pre-push hook enforces PPL thresholds (Std ≤ 12.66, TQ ≤ 13.72) on every kernel change.
  • Known limit on 10 GB cards: prefill attention is O(N²), so the CLI OOMs past ~2 K prompt length regardless of KV compression. See scripts/bench-long-context.sh for the forcing measurement.

Full matrix (Llama 3.1 8B, Mistral 7B, multi-context, reproducible CLIs): BENCHMARKS.md.

What's next (v0.8.0)

Everything below is gated and unscoped; priorities in order:

  • Megakernel wiring. v0.7.0 ships the 6-phase persistent kernel with all stubs promoted to real bodies and the >48 KB shmem opt-in; the last mile is routing TQ_MEGAKERNEL=1 through model.rs::forward. Architect projection +~10 %; will be measured, not claimed, at merge.
  • Flash-attention for PREFILL. We only have flash_decode (single-token). Prefill attention's N×N score tensor is the real long-context OOM cliff; a flash-prefill port unlocks ≥ 4 K contexts on 10 GB cards.
  • EAGLE acceptance debug. Sprint 1–3 shipped the draft loader, tree attention, and acceptance probe in v0.7.0. The draft forward is bit-correct against a numpy reference but acceptance sits at ~6.7 % — a torch-based reference covering non-zero inputs is the likely unlock. Week-scale.
  • Metal backend kickoff (blocked on a collaborator with Apple Silicon).

Full plan: see the status:planned nodes in the project knowledge graph.


The Compound Error Problem

GGUF quantized models (Q4_K_M) already have weight quantization noise. Compressing KV cache on top introduces compound error through softmax. tq-kv solves this with a multi-stage pipeline:

ConfigQwen 7B Q4_K_M PPLStatus
No compression4.136Baseline
tq-kv 4-bit4.457 (+8%)Production
tq-kv 4-bit + TriAttention4.574 (+11%)Constant memory
tq-kv 4-bit (no calibration)~15+Needs auto-calibrate

Key innovations for GGUF compound error:

  • 3-Fix framework: sink tokens (FP16), current token (lossless POQ), cache reset
  • Pre-RoPE quantization: position-independent per-channel stats, better codebook fit
  • Per-token mean removal: softmax shift-invariance exploited, +40% attention quality at 2-bit
  • Auto-calibration: zero-config — calibrates on first use (256 samples, 2-3 seconds)

Measured Quality (Honest Numbers)

All PPL measured with automated tq perplexity / tq ablate.

GGUF Q4_K_M Models (compound error)

Qwen 2.5 7B Q4_K_M, modern English, skip=4, sink=4

ConfigPPLvs BaselineCompression
Baseline (no TQ)1.823--1x
Pre-RoPE 4-bit1.890+3.7%~7.5x
Standard 4-bit1.925+5.6%~7.5x
TQ + Compact (500t/30%)2.227+22.2%~25x
Pre-RoPE + Compact (500t/30%)2.281+25.1%~25x
Full stack (Pre-RoPE+V4+Compact)2.84+55.8%~100x

Pre-RoPE Improvement Across Context Lengths

TokensBaselineStandard TQ (delta)Pre-RoPE (delta)Gap Reduction
4755.1175.820 (+13.7%)5.403 (+5.6%)59%
7934.9015.250 (+7.1%)5.125 (+4.6%)35%
21061.8231.925 (+5.6%)1.890 (+3.7%)34%

Value Compression is Nearly Free

Value ConfigExtra PPL vs K-onlyValue Savings
V-fp16 (default)--1.0x
V-8bit (TQ_VBITS=8)+0.2%2.0x
V-4bit (TQ_VBITS=4)+1.3%3.2x

FP16 Models (no compound error)

Qwen 2.5 0.5B FP16 safetensors, wikitext-2

BitsPPLvs BaselineCompression
Baseline10.740--1.0x
4-bit11.967+11.4%7.5x
2-bit27.696+157.9%14.2x

Compression Quality (per-layer)

ModelBitsRatioSNR (dB)Cosine Sim
Llama-3 8B214.2x9.20.943
Llama-3 8B47.5x20.40.996
Gemma 3 4B215.1x9.20.943

NIAH (Needle-In-A-Haystack)

Bit Width10%25%50%75%90%
4-bitPASSPASSPASSPASSPASS
2-bitPASSPASSPASSPASSPASS

Quick Start

Install

[dependencies]
tq-kv = "0.6"

CLI (tq-engine)

# Pull a model
tq pull qwen2:7b

# Chat with TurboQuant compression
tq chat qwen2:7b --turbo-quant

# Chat with Pre-RoPE (best quality)
TQ_PRE_ROPE=1 tq chat qwen2:7b --turbo-quant

# Start OpenAI-compatible API server
tq serve --model qwen2:7b --turbo-quant --port 11435

# Evaluate perplexity
tq perplexity --model qwen2:7b eval.txt --turbo-quant

# Calibrate (optimal codebook + rotation from real activations)
tq calibrate qwen2:7b --text calibration_data.txt

# Run ablation study
tq ablate qwen2:7b --file eval.txt --quick --output results.csv

Library API

use tq_kv::*;

let config = TurboQuantConfig::balanced(); // 4-bit, 7.5x compression
let dim = 128;

// Batch compress
let compressed = compress_keys(&kv_data, dim, &config);
println!("Ratio: {:.1}x", compressed.compression_ratio());

// Fused attention -- no decompression, AVX2+FMA SIMD
let signs = hadamard::generate_signs(dim, config.rotation_seed);
let centroids = codebook::get_centroids(config.bits);
let rotated_q = pre_rotate_query_with_signs(&query, &signs);
let scores = fused_attention_scores(&rotated_q, &compressed, centroids, scale);

// KV Compaction -- reduce token count
let compacted = compaction::compact_head(&keys, &values, &queries,
    seq_len, n_queries, dim, target_size);
// compacted.keys, compacted.beta, compacted.values

How It Works

Input KV vector (from GGUF Q4_K_M model)
    |
[0] Pre-RoPE capture (optional)            O(1)
    |  Compress BEFORE RoPE for position-independent stats
    |
[1] Channel bias subtraction (calibrated)   O(d)
    |  Remove weight-quantization artifacts
    |
[2] Per-token mean removal                   O(d)
    |  Softmax shift-invariant: attention ignores mean
    |  Frees codebook precision (+40% cosine sim @ 2-bit)
    |
[3] Randomized Hadamard Transform            O(d log d)
    |  Decorrelates outliers -> coordinates ~ Gaussian
    |
[4] Per-channel adaptive sigma (KIVI-style)  O(d)
    |  Per-dimension variance from calibration
    |  Lloyd-Max codebook + norm correction
    |
[5] SRHT QJL Error Correction (optional)     O(d log d)
    |  Structured Hadamard projection (+4.5 dB SNR)
    |
Output: packed indices + corrected norm + mean
        7.5x compression at 4-bit (keys only)

3-Fix for GGUF Models

Fix 1: Sink tokens (first 4) stay FP16     -> -81% attention error
Fix 2: Current token = lossless (POQ)       -> highest-impact position protected
Fix 3: Cache reset per conversation         -> prevents cross-contamination

6-Segment Attention

[sink FP16] [cold decayed] [compacted + beta] [hot compressed] [current FP16]
     |            |                |                   |                |
  Always       Temporal        Attention-           Per-head          POQ
  lossless     decay           matching             adaptive         lossless
  (Fix 1)                      reduction            bitwidth         (Fix 2)
                                    ^
                              TriAttention eviction scores all segments,
                              keeps top-B tokens, maintains fixed budget

TriAttention: Constant-Memory KV Cache

Based on TriAttention (Mao et al., 2026). Pre-RoPE Q/K vectors concentrate around fixed centers, enabling cheap trigonometric importance scoring without full attention computation.

Orthogonal to TurboQuant: TriAttention decides which tokens to keep (eviction), TurboQuant decides how to compress them (quantization). Combined: fixed-size KV cache at any context length.

# TQ+TriAttention is ON by default with --turbo-quant (requires calibration)
tq chat qwen2:7b --turbo-quant

# Disable TriAttention (TQ-only mode)
TQ_TRIATTN=0 tq chat qwen2:7b --turbo-quant

# Custom budget
TQ_TRIATTN_BUDGET=256 tq chat qwen2:7b --turbo-quant

Memory Projection (Qwen2.5-7B, TQ 4-bit + TriAttention, budget=128)

Context LengthFP16 KVTQ 4-bitTQ + TriAttnTotal Compression
4K tokens235 MB154 MB4.8 MB49x
32K tokens1,879 MB1,233 MB4.8 MB390x
128K tokens7,516 MB4,933 MB4.8 MB1,560x

Speed vs Budget (RTX 3080, Qwen2.5-7B, 100 tokens)

Budgettok/svs TQ onlyFixed KV Memory
51215.3-6%19.3 MB
25615.3-6%9.6 MB
12813.8-15%4.8 MB
647.9-46%2.4 MB
(none)16.2--grows linearly

What Fits in 10GB VRAM (5GB available for KV cache)

MethodMax Context Length
FP16 KV~87,000 tokens
TQ 4-bit~133,000 tokens
TQ + TriAttentionunlimited

Configuration Guide

Use CaseKey ConfigPPL ImpactCompression
Best qualityTQ_PRE_ROPE=1+3.7%~7.5x
Balanced--turbo-quant (default)+5.6%~7.5x
Maximum savingsTQ_PRE_ROPE=1 TQ_VBITS=4+5.0%~24x
Long contextTQ_PRE_ROPE=1 TQ_COMPACT=1000 TQ_COMPACT_RATIO=30+30%~50x
ExtremePre-RoPE + V4 + Compact+56%~100x
Unlimited contextTQ_TRIATTN=1 TQ_TRIATTN_BUDGET=256TBDconstant 10 MB

Environment Variables

VariableDefaultDescription
TQ_SKIP4Initial layers kept uncompressed (fp16 KV)
TQ_PROTECT_LAST0Final layers kept uncompressed (boundary protection)
TQ_SINK4Initial tokens preserved at fp16 (attention sinks)
TQ_PRE_ROPE0Pre-RoPE key quantization (1=enabled, best quality)
TQ_COMPACT0Compaction threshold (0=off, e.g. 500=compact when >500 hot tokens)
TQ_COMPACT_RATIO5Compaction target (% of original tokens to keep)
TQ_VBITS0Value compression bits (0=fp16, 4=4-bit, 8=8-bit)
TQ_SPARSE_V1e-6Skip V rows where softmax weight < threshold
TQ_FUSED0Fused attention from compressed indices (CPU only)
TQ_DECAYoffTemporal decay (format: "age:bits" e.g. "512:2")
TQ_LAYER_BITS--Per-layer bit width (format: "start-end:bits")
TQ_HEAD_BITS--Per-head bit width (format: "0-3:4,4-7:2")
TQ_GROUP32Group size for per-group sigma
TQ_BIAS_CORRECT0Softmax bias correction (experimental)
TQ_NO_CAL0Disable calibration auto-loading
TQ_TRIATTNonTriAttention eviction (on by default with --turbo-quant, 0=disable)
TQ_TRIATTN_BUDGET2048Max KV tokens to retain (lower = more aggressive eviction, e.g. 128/256/512)
TQ_TRIATTN_INTERVAL128Eviction check interval in tokens
TQ_CENTER_KEYS1Per-token mean removal (softmax shift-invariant, +40% @ 2-bit)
TQ_MAX_SEQ2048Maximum KV cache sequence length
TQ_NO_PER_CHANNEL0Disable per-channel sigma (KIVI-style, for A/B testing)
TQ_CUDA_ARCHESallCUDA target arches (e.g. "86" for dev, "75,80,86,89,90" for release)

VRAM Savings

ModelContextFP16 KVTQ 4-bitTQ 2-bitSavings
Qwen 2.5 7B4K256 MB34 MB18 MB7.5-14.2x
Qwen 2.5 72B4K640 MB85 MB45 MB7.5-14.2x
Llama 3.1 70B32K20 GB2.7 GB1.4 GB7.5-14.2x

With KV Compaction: effective compression reaches 100-400x. With TriAttention: constant-memory KV cache -- up to 1,560x at 128K context.


SRHT QJL Performance (32K vectors, d=128, release)

MetricDense QJL (paper)SRHT QJL (ours)No QJL
Compress overhead29x1.45x1.0x
SNR improvement+1.2 dB+4.5 dB--
Attention KL div.--2.9x lower--

Full Product: tq-engine

tq-kv powers tq-engine -- "Rust's Ollama" with TurboQuant compression:

tq pull qwen2:7b          # download from HuggingFace
tq serve --turbo-quant     # OpenAI-compatible API (SSE streaming)
tq chat qwen2:7b           # terminal chat

Web UI at localhost:11435. Works with ChatBox and Open WebUI.

4 validated models: Qwen2.5 7B/0.5B, Llama 3.1 8B, Mistral 7B. Auto-detected from GGUF metadata.

3-Way Benchmark

tq bench qwen2:7b                    # Standard vs TQ vs TQ+TriAttention
tq perplexity -m qwen2:7b --compare eval.txt  # 3-way PPL comparison
scripts/ppl-check.sh                  # Regression CI (9 checks, tight thresholds)

GPU Inference Performance

RTX 3080 10GB, Qwen 2.5 7B Q4_K_M, own CUDA kernels (no candle dependency). Full reproducible matrix in BENCHMARKS.md.

Modetok/sTTFTPPLKV Memory
Standard28.00.19s4.136grows linearly
TQ 4-bit19.70.10s4.457 (+7.8%)3.8x smaller
TQ+TriAttention19.40.11s4.574 (+10.6%)constant

4 validated models: Qwen2.5 7B/0.5B, Llama 3.1 8B, Mistral 7B. Auto-calibration on first use.

Custom CUDA Kernel Stack (78 kernels, 16 files, 4.4K lines)

  • Multi-arch: sm_75 (Turing) → sm_90 (Hopper), runtime GPU detect, per-arch PTX
  • Butterfly reduce: __shfl_xor_sync broadcast to all threads (no broadcast hacks)
  • cp.async pipeline: double-buffered qmatmul on Ampere+ (sm_80+), sync fallback on Turing
  • Fused layer kernels: RmsNorm + Q4K QKV + bias, gateup + SiLU, down + residual
  • Q4K/Q6K/Q8_0 fused matvec: __ldg read-only cache, dequant + dot in single kernel
  • Flash decode v2: split-KV parallelism for long context (>256 tokens), online softmax
  • TQ fused attention: compressed KV → attention score without decompression (moat kernel)
  • CUDA Graph replay: short context (<256) as single GPU operation, auto-fallback to eager mode

Optimization History

Phasetok/sKey Change
Baseline (candle)1.3candle framework
Custom CUDA kernels1.9Own matvec, RoPE, attention
DecodeScratch + fused10.1Zero-alloc decode, fused kernels
GPU prefill + CUDA Graph17.8Graph replay, Q6K lm_head
v2 kernels + multi-arch18.5__ldg, warp-reduce, cp.async, butterfly reduce
cp.async weight pipeline23.3MLP gateup + MLP down + qmatmul cp.async W-prefetch
mrow ladder (v0.6, shipped 2026-04-14)28.0cooperative-per-superblock gateup/down, RoPE Q+K fuse, bias-fused LM head

Benchmark

cargo run --release -p tq-kv --bin tq-kv-bench

Full results: BENCHMARK.md

Paper

Our work:

  • "TurboQuant on Quantized Models: Solving Compound Quantization Error with Pre-RoPE Compression and KV Compaction" -- BHI Research (2026)
  • 3-Fix framework, SRHT QJL (115x speedup), Pre-RoPE quantization, KV Compaction, Adaptive QJL

Original:

  • Zandieh, Daliri, Hadian, Mirrokni. "TurboQuant: Online Vector Quantization with Near-optimal Distortion Rate." ICLR 2026. arXiv:2504.19874
  • Mao, Lin, Huang et al. "TriAttention: Efficient Long Reasoning with Trigonometric KV Compression." 2026. arXiv:2604.04921

License

MIT OR Apache-2.0

Contributors

Languages

Rust

75.6%

Cuda

18.3%

HTML

2.8%

Shell

1.4%

C

1.0%