LoopKV: Loop-Aware KV Cache Compression for Serving Looped Transformers
Organizations: Harvard University · University of California San Diego · University of Chicago
Abstract
Looped transformers apply a shared block several times per token to improve accuracy without adding parameters. For models such as Ouro that keep a separate key-value (KV) cache per loop, cache memory limits the batch size that amortizes repeated weight reads. Uniform-bit quantization and fixed rules per loop do not allocate precision according to each layer's sensitivity in each loop. Measurements on Ouro show that quantization sensitivity varies across (loop, layer) cells, and the sum of individual cell damages approximates the overall output damage. Sharing damage also varies by cell, with later loops generally tolerating sharing better. Skipping low-attention values to save reads produces errors that compound across loops. LoopKV uses a one-time offline profile to choose 4-bit storage, 2-bit storage or reuse of the final loop's KV for each cell. The planner minimizes reads under budgets for predicted damage and storage. During decoding, each loop reads the high 2 bits of each 4-bit value and fetches the low bits only where its own attention weights require 4-bit precision. A single fused kernel in vLLM executes the plan. Serving Ouro-1.4B on one RTX PRO 6000, the memory-optimized LoopKV-M plan stores 35% less KV than uniform 4-bit quantization (KIVI-4) on the same fused kernel and CUDA graph. It sustains 1.7-2.2x KIVI-4's goodput under a latency service-level objective with a 16K-token maximum length. None of its averages on six public benchmarks falls significantly below BF16's.
Figures & tables
| R16K | R32K | LB | MATH500 | GSM8K | L5 | |
| Ouro-1.4B | ||||||
| BF16 | 71.44 | 54.04 | 25.29 | 84.5 | 76.6 | 70.6 |
| LoopKV-M | 72.12 | 53.63 | 25.19 | 86.0 | 77.1 | 71.1 |
| LoopKV-R | 72.49 | 53.86 | 25.32 | 84.5 | 76.6 | 70.3 |
| KIVI-4 + V | 71.37 | 54.57 | 25.25 | 84.5 | 76.9 | 72.0 |
| INT2, loops 1–3 | 65.50 | — | 24.43 | 86.0 | 77.0 | 69.3 |
Appendix figures & tables27 assets
Supplementary material from the paper’s appendix.
Appendix
| plan | fp32 KL | MQ641 (stress) | RULER-style 16K | MATH500 (200) | GSM8K (1,319) | long reasoning (194) | |
| LoopKV | read-optimized | 0.87 | — | — | — | ||
| + V precision | 0.87 | ||||||
| memory-optimized | 1.80 | — | |||||
| + V precision | 1.80 | — | — | ||||
| baselines | KIVI-4 | 0.46 | — | — | — | ||
| KIVI-2 | 21.5 | to | — | — | — | — |
| arm | official RULER-16K | official RULER-32K | LongBench v1 (16) | MATH500 (200) | GSM8K (1,319) | MQ641 (stress) |
| KIVI-4 + V | ; vt | ; qasper , gov_report | ||||
| LoopKV-R | ; qa_1 | ; multifieldqa_en | ||||
| LoopKV-M | ; fwe , qa_1 | ; vt , fwe , cwe | ||||
| FP8 + loop-3 sharing (as served) | ; vt , cwe | (A100-80); vt , fwe | ; narrativeqa , musique ∗ | — |
| suite (items) | KIVI-4 + V | LoopKV-R | LoopKV-M | KIVI-4 † | KIVI-4 + loop-3 sharing † | FP8 + loop-3 sharing |
| RULER-16K (1,300) | 30 / 37 | 26 / 44 | 54 / 71 | 29 / 31 | 45 / 87 | 66 / 80 |
| RULER-32K (1,300) | 37 / 47 | 44 / 45 † | 84 / 89 | 40 / 47 | — | — |
| LongBench v1 (3,750) | 499 / 480 | 513 / 540 | 556 / 596 | 483 / 495 | 579 / 570 | 681 / 719 |
| MATH500 (200) | 8 / 8 | 9 / 9 | 7 / 10 | — | 9 / 14 | 5 / 9 |
| GSM8K (1,319) | 21 / 25 | 22 / 22 | 27 / 34 | — | 27 / 30 | 59 / 45 |
| long reasoning (194) | — | 34 / 39 † | 33 / 38 † | — | — | — |
| arm | KiB / token | MATH500 (200) | GSM8K (1,319) |
| BF16 | 1,536 | 89.5 | 79.7 |
| KIVI-4 + V | 480 (31%) | 90.5, | 79.5, |
| LoopKV-M | 310 (20%) | 89.5, | 79.5, |
| LoopKV-R | 430 (28%) | 90.5, | — |
| BF16 § | 1,536 | — | 79.8 |
| LoopKV-R § | 430 (28%) | — | 79.2, |
| configuration | bytes | KL | 8K | 16K | same block | host launches |
| KIVI-4 | 240/240 | 0.46 | 494.4 | 249.1 | — | — |
| read-optimized plan (C1) | 215/215 | 0.87 | 528.9 | 271.5 | — | 433 |
| memory-optimized plan (C1 + C2) | 155/220 | 1.80 | 535.1 | 280.7 | — | — |
| + V precision (C3) | 155/189 | 1.80 | 561.6 | 295.5 | 1.044 / 0.98 | 504 |
| + fused kernel | 155/189 | 1.80 | 571.2 | 300.0 | 1.019 / 1.033 | 332 |
| + whole-step CUDA graph (LoopKV-M) | 155/189 | 1.80 | 575.9 | 301.9 | 1.006 / 1.067 | 17 |
| model, GPU | context | BF16 | uniform INT4 | LoopKV-R | LoopKV-M |
| Ouro-1.4B, A100-80 | 8K | 188.4 (10) | 336.6 (27) 1.79 | 377.6 (30) 2.00 | 408.5 (42) 2.17 |
| 16K | 95.0 (5) | 161.3 (11) 1.70 | 189.9 (13) 2.00 | 209.2 (20) 2.20 | |
| 32K | 22.7 (2) | 84.6 (6) 3.73 | 105.4 (8) 4.65 | 107.0 (11) 4.72 | |
| Ouro-2.6B, RTX PRO 6000 | 8K | 81.3 (6) | 208.3 (16) 2.56 | 240.4 (18) 2.96 | 263.9 (23) 3.25 |
| 16K | 30.8 (3) | 109.5 (8) 3.56 | 124.1 (8) 4.03 | 136.8 (11) 4.44 | |
| 32K | 6.2 (1) | 52.7 (4) 8.51 | 58.6 (4) 9.46 | 68.1 (5) 11.0 |
| plan | bytes | 8K | 16K | 32K | BF16 / FP8+S, 8K |
| BF16 | 768/768 | 170.8 (8) | 89.0 (6) | — | 1.00 / 0.48 |
| FP8 | 384/384 | 328.8 (16) | 176.3 (13) | — | 1.93 / 0.92 |
| FP8 + sharing (FP8+S) | 288/384 | 358.4 (33) | 180.7 (16) | — | 2.10 / 1.00 |
| uniform INT4 | 240/240 | 494.4 (34) | 249.1 (14) | — | 2.89 / 1.38 |
| uniform-INT4 + sharing | 180/240 | 505.4 (40) | 264.2 (20) | — | 2.96 / 1.41 |
| + V precision | 180/200 | 521.1 (40) | 277.4 (20) | — | 3.05 / 1.45 |
| capacity (req/s), ms or as noted | first failing rung, , 18.60 ms | ||||||||
| arm | seed | rungs (req/s) | , 20.69 | attainment | T / P / B | preempt. | |||
| BF16 | 101 | 0.0119–0.0170 | 0.0119 | 0.0119 | 0.0170 | 0.0143 | 0.605 | 0 / 17 / 0 | 3 |
| FP8 | 101 | 0.0305–0.0476 | 0.0305 | 0.0381 | 0.0476 | 0.0381 | 0.535 | 0 / 20 / 0 | 6 |
| FP8 + sharing | 101 | 0.0305–0.0476 | 0.0305 | 0.0305 | 0.0476 | 0.0381 | 0.930 | 0 / 3 / 0 | 0 |
| uniform INT4 | 101 | 0.0476–0.0714 | 0.0476 | 0.0476 | 0.0595 | 0.0595 | 0.930 | 1 / 2 / 0 | 92 |
| 102 | 0.0476–0.0952 | 0.0476 | 0.0833 | 0.0833 | 0.0833 | 0.857 | 5 / 0 / 2 | 93 | |
| arm | 8K peak | 16K peak | , 8K (ms) | MATH500 (%) | GSM8K (%) |
| BF16 | 1.00 | 1.00 | 10.68 | 83.2 | 76.6 |
| FP8 | 2.08 | 2.05 | — | — | — |
| KIVI-4 | 2.27 | 1.96 | 10.63 | 83.2 | 77.0 |
| KIVI-4 + V | 2.26 | 1.96 | 10.55 | 85.4 | 76.5 |
| LoopKV-R | 2.54 | 2.41 | 10.35 | 84.6 | 76.8 |
| LoopKV-M | 2.69 | 2.69 | 10.33 | 84.4 | 77.0 |
| KV format | stored | read | tok/s 8K / 16K |
| BF16 | 768 | 768 | 170.8 / 0 89.0 |
| BF16 + loop-3 sharing ( ) | 576 | 768 | 182.1 / 0 95.8 |
| FP8 | 384 | 384 | 328.8 / 176.3 |
| FP8 + loop-3 sharing | 288 | 384 | 358.4 / 180.7 |
| INT4 final + INT4 residuals | 180 | 360 | 370.3 / 192.0 |
| KIVI-4 + loop-3 sharing | 180 | 240 | 505.4 / 264.2 |
| plan | rule | stored / read | predicted | measured | served KL | tok/s 8K / 16K |
| read-optimized | min reads, damage pred. of INT4 residuals | 215 / 215 | 1.15 | 0.87 | 1.28 | 528.9 / 271.5 |
| memory-optimized | min reads, stored 156, damage pred. of layer-split residuals | 155 / 220 | 1.97 | 1.80 | 1.77 | 535.1 / 280.7 |
| d | min reads, damage 1.42 | 210 / 210 | 1.41 | 1.11 | 1.42 | 519.4 / 276.2 |
| c | min damage, stored 156 | 156 / 321 | 1.09 | 1.08 | 1.41 | 401.9 / 209.1 |
| a | min damage, read 240 | 237 / 240 | 0.67 | 0.47 | 1.01 | 479.8 / 213.0 |
| b | min damage, read 312 | 239 / 312 | 0.49 | 0.37 | 0.98 | 398.0 / 179.3 |
| design | stored / read | tok/s 8K / 16K | served KL | fp32 KL | MQ641 |
| INT4 residuals | 180 / 360 | 370.3 / 192.0 | 1.53 | 1.42 | |
| loop 1 INT4, loop 2 INT2 | 156 / 336 | 386.3 / 199.7 | 1.88 | 2.12 | |
| layer split: layers 1–12 INT4, 13–24 INT2 | 156 / 336 | 385.6 / 200.1 | 1.79 | 1.83 | |
| INT2 residuals | 132 / 312 | 416.8 / 215.9 | 2.97 | 4.38 |
| loops | KL / | full-precision V fraction | read KiB | ||
| 1–2 | 3 | 2.261 | .001 / .000 | 216.0 | |
| 1–2 | 6 | 1.768 | .008 / .002 | 216.1 | |
| 1–2 | 8 | 1.606 | .020 / .007 | 216.3 | |
| 1–2 | 10 | 1.502 | .042 / .024 | 216.8 | |
| 1–2 | 12 | 1.492 | .090 / .067 | 217.9 | |
| 1–2 | 16 | 1.501 | .321 / .303 | 223.5 |
| hot fraction of the far history, | Jaccard of hot sets, | ||
| loop 1 / 2 / 3 / 4 | .27 / .24 / .25 / .25 | loop 1 vs 2 / 3 / 4 | .44 / .40 / .39 |
| union of 4 loops | .37 | loops 2–3 / 2–4 / 3–4 | .63 / .57 / .76 |
| shared cell 3s | .25 | 3s vs 4 | .83 |
| V lo-plane bytes, write-time per-token precision / per-loop read-time rule: 2.2 ( ), 1.6 ( ), 1.3 ( ) | |||
| component | plain | + V precision (window seed) | + V precision (sink seed) |
| history reader | 53.69 | 50.38 | 50.71 |
| seed | — | 2.02 | 0.51 |
| sink + window FlashAttention-2 | 7.17 | 7.21 | 7.21 |
| GEMMs | 8.23 | 8.29 | 8.28 |
| GPU busy | 71.38 | 70.42 | 69.07 |
| cell | BF16 INT2 | BF16 INT8 | BF16 1 ulp | fp32 INT2 | fp32 INT8 | fp32 1 ulp | fp32 INT2 / ulp |
| loop 1, layer 1 | 1.63e-4 | 1.37e-4 | 1.37e-4 | 2.89e-5 | 7.5e-8 | 8.3e-8 | 348 |
| loop 1, layer 12 | 1.44e-4 | 1.23e-4 | 1.25e-4 | 1.78e-5 | 3.0e-8 | 3.2e-8 | 561 |
| loop 2, layer 12 | 1.18e-4 | 1.10e-4 | 1.08e-4 | 7.53e-6 | 4.2e-9 | 1.7e-8 | 433 |
| loop 3, layer 12 | 0.98e-4 | 0.98e-4 | 0.98e-4 | 8.30e-7 | 1.0e-9 | 7.2e-9 | 115 |
| loop 3, layer 24 | 0.92e-4 | 0.90e-4 | 0.90e-4 | 9.26e-8 | 1.2e-10 | 3.4e-9 | 27 |
| model | bytes | knapsack | uniform, first | uniform, last |
| Dory-4B | 1.33 | 2.00 | 29.3 | |
| Dory-4B | 2.44 | 2.92 | 33.4 | |
| Huginn-3.5B | 1.04 | 1.20 | 85.0 | |
| Huginn-3.5B | 2.78 | 3.62 | 98.3 |
| plan | stored / read | KL | + V precision (read) | V precision |
| KIVI-4 | 480 / 480 | 0.82 | — | — |
| KIVI-4 + loop-3 sharing | 360 / 480 | 1.86 | — | — |
| INT4/INT2 + sharing | 312 / 432 | 6.30 | — | — |
| INT2 + sharing | 264 / 384 | 12.70 | — | — |
| read-optimized (knapsack) | 430 / 430 | 1.39 | 1.41 (374.1) | |
| memory-optimized (knapsack) | 310 / 430 | 3.04 | 3.04 (373.9) |
| arm | bytes | MATH500 ( ) | 8K peak | 16K peak |
| last-loop BF16 | 1.00 | 91.5 | 352.0 (40) | 219.7 (24) |
| LoopKV-R | 0.85 | 91.5 ( ) | 352.9 (40) | 221.6 (24) |
| LoopKV-M | 0.54 | 91.7 ( ) | 362.5 (56) | 247.9 (48) |
| rec5 (fixed) | 0.62 | 91.7 ( ) | 367.7 (56) | 254.8 (40) |
| full9 (fixed) | 0.31 | — | 370.3 (48) | 259.6 (56) |
| context | KIVI-4 | KIVI-4 + V | LoopKV-R | LoopKV-M | gain, own peak (LoopKV-R / -M) | gain, same batch (LoopKV-R / -M) |
| 8K | 190.4 (10) | 202.9 (10) | 218.9 (11) | 242.2 (15) | 1.078 / 1.194 | 1.042 / 1.036 |
| 16K | 100.7 (5) | 109.1 (5) | 122.3 (6) | 132.6 (8) | 1.121 / 1.215 | 1.037 / 1.031 |
| 32K | 47.2 (2) | 50.6 (2) | 60.2 (3) | 65.5 (4) | 1.190 / 1.293 | 1.042 / 1.033 |
| design | bytes | KL | resident batch | tok/s |
| 32-token groups with V precision: served | ||||
| KIVI-4 + V | 240/240 | 0.46 | 1 | 1 |
| + loop-3 sharing (hand-made) | 180/240 | 1.51 | 1.33 (1.43) | 1.07 |
| LoopKV-R (knapsack) | 215/215 | 0.87 | 1.12 (1.14) | 1.08 (1.08) |
| LoopKV-M (knapsack) | 155/220 | 1.80 | 1.55 (1.71) | 1.16 (1.13) |
| format | bits / element | KiB per token | KL | KL with Hadamard |
| KIVI-4, group 32 (asymmetric INT4) | 5.0 | 240 | 0.46 | 0.31 |
| INT4 symmetric, group 16 | 5.0 | 240 | 1.25 | 0.67 |
| NVFP4 (blocks of 16, E4M3 scale) | 4.5 | 216 | 2.08 | 0.97 |
| MXFP4 (blocks of 32, E8M0 scale) | 4.25 | 204 | 6.40 | 2.46 |
| FP8 E4M3 (reference) | 8.0 | 384 | 0.19 | — |
KV-Cache Compression
Key-value cache compression reduces the memory and bandwidth needed to retain attention states during long-context inference.
See all 279 papers