turbo-attn · KV-cache compression · fidelity

Smaller Memory, Same Answers

While a model writes, it keeps a running memory of everything it has read, the KV cache. Compressing it lets one GPU serve more conversations. We compared our compression (turbo-attn) against the KV-cache quantizations currently available in vLLM, all measured the same way in the same engine.

3–4× closerto uncompressed quality than any other 4-bit option: 98.92% of words unchanged vs 97.63% (int4) and 97.20% (vLLM 4-bit), against 99.53% uncompressed
5 bits = FP8Our 5-bit setting matches FP8's fidelity (99.24% vs 99.24%) in 37% less memory: 3.2× capacity vs 2.0×. At 5.5 bits we are ahead of FP8 (99.34%).
3 bits beats every 4-bit optionOur 3-bit setting (98.02%) is more faithful than every other method at 4 bits, with 25% less memory.
8 bits ≈ losslessOur 8-bit setting (99.48%) is within measurement noise of uncompressed (99.53%); FP8 scores 99.24%.

"Words unchanged" = how often the model writes the same next word as with uncompressed memory, under normal sampling. "Closer" compares each method's gap to uncompressed: ours 0.6 points at 4 bits vs 1.9 (int4) and 2.3 (vLLM 4-bit). All numbers: Qwen3.5-0.8B in vLLM 0.28.0 with our vllm-turbo patches; method and provenance at the bottom.

What makes it work

turbo-attn is not one trick. Each piece below removes a different source of error; all of them were switched on for the measurements on this page (details at the bottom).

calibrate

Data calibration

Every model is calibrated on its own activations, captured from real text. Rotations, scales and codebooks are all fit from that data, not from generic assumptions.

rotate

Hadamard rotation

A fast Walsh–Hadamard transform spreads outlier channels across the whole vector so every coordinate quantizes alike. Queries are rotated the same way, so attention scores need no un-rotation.

rotate

OSCAR

A rotation fitted per layer and KV head on top of Hadamard: for keys, the directions the queries actually probe; for values, the directions that actually reach the output. Bits go where attention looks.

scale

Normalisation

Each vector's length is stored once as a bf16 number and only its direction is quantized, with a key-side norm correction so the decoded key keeps its true length.

scale

Per-channel scales

Calibrated scales stretch each channel to fill the codebook's range before quantizing, so quiet channels are not wasted and loud ones do not clip.

quantize

Fitted codebooks

Instead of evenly spaced levels, each layer and bit width gets Lloyd-Max levels fitted to its calibrated value distribution (5–8 bits).

quantize

vq2

At 2–4 bits, pairs of channels are quantized together against a 2-D codebook (4b entries per pair), which captures how neighbouring values move together.

attend

Fresh diagonal

While a prompt is being read, its newest chunk attends to its own fresh values instead of the compressed codes; only older context is read from the codes. (With the fast prompt-reading kernel used here, those fresh values are held at 8 bits.)

attend

Fidelity ring

Each conversation's newest 128 positions, the ones decoding leans on hardest, are also kept at 8 bits beside the codes and read from there.

Additional levers, not used in these results

These are built into turbo-attn and can be switched on, but every result on this page used the default, faster setting. They are extra room to trade a little speed or effort for more faithfulness. We are not claiming they win on this test.

allocate

SmartMix

Gives each layer its own bit width under a fixed memory budget, chosen by calibration, instead of the same width everywhere. Enabled with a fractional budget such as TKV_BITS=4.5 and a SmartMix-calibrated file. These results used one width for every layer.

attend

Exact tensor-core arithmetic

Adds up the attention scores without the rounding the fast tensor-core path allows, at some cost in speed. TKV_MMA_PRECISION=exact. These results used fast.

attend

32-bit working tile

Keeps the decoded memory in 32-bit instead of 16-bit while attending, using the non-tensor-core kernel. TKV_DECODE_SMEM_HALF=0. These results used the 16-bit tile.

read prompt

Full-precision prompt reading

Reads the prompt with bf16 arithmetic instead of the fast 8-bit kernel, keeps the newest chunk at bf16, or spends a time budget on finer splits. TKV_PREFILL_INT8=0, TKV_PREFILL_INT8_FRESH_S8=0, TKV_PREFILL_INT8_SPLIT_FIDELITY. These results used the 8-bit kernel with the newest chunk at 8 bits.

Memory vs. faithfulness

How to read this chart. Each dot is one way of compressing the memory. Further left uses less memory. Higher up means the model writes more like the original. Top-left is best. Blue dots are ours, orange are the quantizations currently available in vLLM, and the dotted grey line is uncompressed memory.

Showing how often the model writes the same next word as the original. Our K4V4 setting matches 98.92% of the time; uncompressed memory matches 99.53%.

ours (tkv)our best at each size7currently available in vLLMuncompressed6
  1. Same words (the main measure): how often the model picks the same next word as the uncompressed original when it writes normally, with its usual randomness.
  2. Same top choice: how often the model's single favourite next word is unchanged. This is a looser test.
  3. Same full distribution: how closely the model's whole list of word probabilities matches, including unlikely words. This is the strictest test.
  4. Memory per number: bits used to store each number in the memory, including bookkeeping. Uncompressed memory uses 16.
  5. vLLM 3-bit is left off the chart because it scores much lower (93.6% same words). It is in the table.
  6. Uncompressed (bf16) is the normal memory format. Even it is not a perfect match to the full-precision reference.
  7. The dashed blue line joins our best result at each memory size.
  8. The thin vertical lines show the range each result could fall in by chance (95% confidence). Dots whose lines overlap cannot be told apart.

All results

codecmemory per numberfits in the same memorywords unchanged¹
K2V2ours2.06 bits7.76×95.72%
K3V2ours2.56 bits6.24×96.99%
K3V3ours3.06 bits5.22×98.02%
vLLM 3-bitother3.09 bits5.17×93.62%
K4V3ours3.56 bits4.49×98.59%
vLLM K3/V4other3.59 bits4.45×96.64%
K4V4ours4.06 bits3.94×98.92%
vLLM 4-bitother4.09 bits3.91×97.20%
vLLM int4other4.12 bits3.88×97.63%
K5V4ours4.56 bits3.51×99.15%
K6V4ours5.06 bits3.16×99.24%
K6V5ours5.56 bits2.88×99.34%
K6V6ours6.06 bits2.64×99.40%
vLLM K8/V4other6.06 bits2.64×97.46%
FP8other8.00 bits2.00×99.24%
K8V8ours8.06 bits1.98×99.48%
vLLM int8other8.12 bits1.97×99.46%
Uncompressed (bf16)baseline16.00 bits1.00× (baseline)99.53%

Small differences are within the margin of error, for example K8V8 against uncompressed memory.

How we measured
  • Model: Qwen3.5-0.8B with normal (bfloat16) weights. Only the memory format changes between rows.
  • Test: 32 long prompts. Every method is scored on the same 1480 next-word positions per prompt against a full-precision (FP32) reference, 47,384 positions in total.
  • Same words is 1 − TVD (total variation distance) under the served sampler (temperature 1.0, top-k 20, top-p 0.95). Same top choice is top-1 agreement. Same full distribution is e−KL, with KL estimated over the 64 most likely words. Ranges are 95% bootstrap intervals over prompts.
  • Memory is the bytes each engine actually reserved, including metadata. "Fits in the same memory" is relative to uncompressed bf16. This model also keeps a fixed 18.6 MiB per conversation for its other (GDN) layers, which compression does not change.
  • Our settings: OSCAR rotation (basis oscar:4e855d3b37) over Hadamard, per-channel scales, key norm correction, vq2 codebooks at 2–4 bits and Lloyd-Max codebooks at 5–8 bits, fresh diagonal on (TKV_FRESH_DIAGONAL=1), fidelity ring on (128 positions at 8 bits). Kernels: tensor-core attention in fast mode with a 16-bit working tile, and the 8-bit prompt-reading kernel (newest chunk at 8 bits). Where two variants use the same memory, only the better one is shown (K5V4, not K4V5, K6V4, not K5V5, FP8, not FP8 e5m2, vLLM int8, not vLLM fp8 per-token-head).
  • Sanity check: two separate runs of the reference produced identical results at every position.
  • Engine: every row, ours and the others, ran in the same engine: vLLM 0.28.0 with our vllm-turbo patch set (image registry.arbi.work/vllm-turbo:latest, sha256:6f59874954cc…), eager mode, max length 16,384, GPU memory fraction 0.6.
  • The other methods are vLLM's own built-in KV-cache options, run unmodified: fp8 (e4m3), fp8_e5m2, the per-token-head int4/int8/fp8 modes, and the built-in low-bit presets (vLLM names them turboquant_*; shown here as "vLLM 3-bit", "vLLM 4-bit", "vLLM K3/V4", "vLLM K8/V4").
  • Ours: turbo-attn at commit f5e9633a, calibration bundle sha256 88422307…, loaded through the vllm-turbo plugin.
  • Run 37145188480 (kv-ablation-ladder workflow) on 202vmgpu0, 202vmgpu1, 203vmgpu0. Full data and per-row provenance: /mnt/k8scache/paper_kv_ablation/ci/n32-main-20261003-run37145188480/.