Skip to content
Ashish.
All posts
Diagram illustrating KV cache memory compression via quantization.
6 min readDevelopmentML engineers, Infrastructure engineersFeatured#kv cache#quantization#llm optimization#memory efficiency#long context#inference

Quantizing the KV Cache Without Wrecking Quality

Explore techniques for quantizing the KV cache to reduce memory usage and improve throughput for long context windows in LLMs.

By Ashish KumarPart 4 of Quantization in Practice

In large language model (LLM) inference, the Key-Value (KV) cache is the primary bottleneck for long-context performance. As the sequence length grows, the memory required to store past token representations scales linearly, often exceeding GPU memory limits before compute becomes the constraint. Quantizing the KV cache—reducing the bit-width of stored key and value tensors—offers a direct path to higher throughput and longer context windows. However, naive quantization can degrade generation quality because the KV cache contains activation values prone to outliers that are difficult to compress without information loss.

The KV Cache Bottleneck

Schematic flowchart showing the autoregressive generation process, highlighting the growing KV cache buffer as tokens are added, with mathematical notation for memory footprint.

During autoregressive generation, an LLM computes attention over all previous tokens. The attention mechanism requires access to the keys (KK) and values (VV) for every token in the sequence history. These are stored in the KV cache, a buffer that grows by one row per token generated. For a model with dmodeld_{model} dimensions, nlayersn_{layers} transformer layers, and a batch size of BB, the memory footprint is approximately:

Memory=B×L×2×dmodel×nlayers×bytes_per_element\text{Memory} = B \times L \times 2 \times d_{model} \times n_{layers} \times \text{bytes\_per\_element}

Where LL is the sequence length. In a typical 7B parameter model with 4096 hidden dimensions and 32 layers, storing the KV cache in float16 (2 bytes) for a sequence of 8,000 tokens and batch size 1 consumes roughly 4 GB. While this seems manageable, batch sizes increase with shorter sequences, and context lengths in production often exceed 32K tokens. At 32K tokens, the same model requires ~16 GB just for the KV cache, leaving little room for additional batches or larger models. The pursuit of memory savings becomes critical when scaling to long context scenarios where every megabyte counts.

The problem is not just capacity; it’s bandwidth. Reading the KV cache during each decoding step consumes significant memory bandwidth. Reducing the bit-width directly lowers both the storage requirement and the bandwidth needed to fetch these tensors, enabling higher effective batch sizes or longer contexts.

Quantization Techniques: INT8, FP8, and INT4

Comparison chart showing three quantization methods : INT8, FP8, and INT4. Each method is represented by a bar or block showing bit-width, memory usage, and precision quality. FP8 is highlighted as the middle ground.

Quantizing the KV cache involves mapping high-precision floating-point values to lower-bit integers or reduced-precision floats. For kv cache quantization, two main approaches dominate the landscape of optimization strategies.

INT8 Quantization

INT8 quantization represents each tensor element using 8-bit integers. To do this, the system applies a scale factor SS and zero-point ZZ to map the original float range to the integer domain:

Q=round(XS)+ZQ = \text{round}\left(\frac{X}{S}\right) + Z

Where XX is the original float value and QQ is the quantized integer. During inference, the quantized values are dequantized on-the-fly or used in specialized INT8 matmul kernels that avoid full dequantization. Per-tensor scaling (a single scale for the entire tensor) is simple but often insufficient for the KV cache due to its wide dynamic range. Per-token or per-head scaling, where each token or attention head has its own scale factor, preserves more detail at the cost of metadata overhead.

FP8 Quantization

FP8 (E4M3 or E5M2 formats) offers a middle ground between INT8 and float16. FP8 provides 3 bits of mantissa (E4M3) or 2 bits (E5M2), along with exponent bits. This allows it to represent a wider range of values than INT8 while still using less memory than float16. NVIDIA’s Hopper architecture and newer AMD GPUs support native FP8 tensor cores, making fp8 kv cache quantization highly efficient on modern hardware. The key advantage is that FP8 retains some precision for small values, which is critical for attention scores that can be very small.

INT4 and Beyond

INT4 quantization reduces memory further but introduces significant quantization error. For the KV cache, INT4 is rarely used without additional techniques like grouped quantization or mixed precision, because the loss of precision can lead to noticeable degradation in text coherence. However, for extremely long contexts where memory is the absolute constraint, INT4 may be viable if combined with other compression methods like pruning or eviction policies.

Why KV Cache Quantization Is Harder Than Weight Quantization

Quantizing model weights is well-studied because weights are static and trained to be robust to perturbations. The KV cache, however, consists of activations that change dynamically during inference. Activations often exhibit "outliers"—values that are significantly larger than the mean—which dominate the quantization scale. If the scale is determined by the maximum value, most values are quantized to near-zero, losing critical information.

For example, in a self-attention layer, the key vectors might have a few tokens with unusually large norms due to rare vocabulary or complex syntactic structures. A uniform scale factor would compress these outliers into a narrow range, distorting the attention distribution. This distortion can cause the model to attend to the wrong tokens, leading to incoherent generations.

Preserving Quality: Outlier-Aware and Mixed Precision

Diagram illustrating outlier-aware quantization. A distribution curve of KV cache values shows a few large outliers separated from the main cluster. The outliers are stored in high precision (float16) while the main cluster is quantized to INT8.

To mitigate quality loss, several techniques have been developed:

Outlier-Aware Quantization

This approach identifies and protects outlier values. Instead of applying a single scale factor, the system detects values that fall outside a certain percentile (e.g., top 1%) and handles them separately. For instance, outliers might be stored in float16 while the rest are quantized to INT8. This mixed-precision approach preserves the most critical information while still achieving significant memory savings.

Per-Token Scaling

Rather than using a single scale for the entire KV cache, per-token scaling assigns a unique scale factor to each token. This allows the quantization to adapt to the local dynamic range of each token’s key and value vectors. While this increases metadata overhead (one scale factor per token per head), it significantly improves accuracy compared to per-tensor scaling.

Grouped Quantization

Grouped quantization divides the KV cache into smaller groups (e.g., by head or by layer) and applies separate scale factors to each group. This reduces the impact of outliers by isolating them within a group, allowing the rest of the values to be quantized more precisely.

Post-Training Calibration

Before deploying a quantized model, engineers perform calibration by running a small dataset through the model and collecting statistics on the KV cache values. These statistics inform the choice of scale factors and zero-points. Calibration ensures that the quantization ranges are aligned with the actual distribution of values encountered during inference, rather than relying on theoretical bounds.

Practical Implementation Considerations

When implementing kv cache quantization, engineers must consider several factors related to llm optimization and memory efficiency:

  1. Hardware Support: Not all GPUs support efficient INT8 or FP8 inference. Check your hardware’s capabilities before choosing a quantization format. NVIDIA H100, AMD MI300, and newer NVIDIA GPUs support native FP8 tensor cores. For INT8 support, older architectures like A100 are still relevant, but FP8 requires Hopper or newer.

  2. Framework Support: Libraries like Hugging Face Transformers, vLLM, and TensorRT-LLM offer built-in support for KV cache quantization. For example, vLLM supports FP8 KV cache quantization out of the box, while TensorRT-LLM provides tools for calibrating and deploying quantized models.

  3. Latency vs. Throughput: Quantization reduces memory bandwidth, which can improve throughput. However, the overhead of quantizing and dequantizing values can add latency. Benchmark both metrics to determine the optimal trade-off for your use case.

  4. Quality Evaluation: Always evaluate the impact of quantization on generation quality. Use metrics like perplexity, BLEU, or human evaluation to ensure that the compressed KV cache does not degrade output coherence. Pay special attention to long-context tasks, where the KV cache is most critical for inference stability.

Common Pitfalls

When adopting KV cache quantization, engineers often encounter specific traps that undermine performance:

  1. Ignoring Outlier Distribution: Assuming a uniform distribution of activation values leads to catastrophic precision loss. Outliers often carry semantic importance; failing to isolate them results in incoherent outputs.
  2. Using Per-Tensor Scaling for High-Variance Models: Global scale factors are too coarse for models with high activation variance. This leads to significant quantization error, particularly in attention heads that exhibit distinct dynamic ranges.
  3. Overlooking Framework Support: Attempting to implement custom quantization logic without leveraging existing framework optimizations (like vLLM’s PagedAttention) can introduce subtle bugs and performance regressions.

Practical Takeaways

For engineers looking to implement these optimizations, consider these key actions:

  • Start with FP8 on Supported Hardware: If your GPU supports FP8 tensor cores, prioritize FP8 over INT8 for better precision retention with minimal overhead.
  • Implement Outlier Protection: Use mixed-precision schemes where outliers are stored in higher precision (e.g., float16) while the bulk of the cache uses lower precision (e.g., INT8).
  • Benchmark Rigorously: Always measure both throughput (tokens/sec) and latency (TTFT, ITL) alongside quality metrics like perplexity to ensure the trade-offs are justified.

FAQ

Q: Does KV cache quantization affect training? A: No, KV cache quantization is strictly an inference-time optimization. Training involves backpropagation and gradient computation, which require full precision.

Q: How much memory can I save with INT8 vs. Float16? A: INT8 quantization reduces the memory footprint by approximately 50% compared to Float16, as each element uses 8 bits instead of 16 bits.

Q: Is FP8 KV cache quantization widely supported? A: Support is growing rapidly. Major frameworks like vLLM and TensorRT-LLM support it, but it requires hardware with FP8 tensor cores (e.g., NVIDIA H100, H200, or Blackwell).

Conclusion

Quantizing the KV cache is an effective method for improving LLM inference efficiency, especially for long-context applications. By reducing the bit-width of stored key and value tensors, engineers can significantly lower memory usage and increase throughput. However, the dynamic nature of activations and the presence of outliers make KV cache quantization more challenging than weight quantization. Techniques like outlier-aware quantization, per-token scaling, and mixed precision are essential for preserving generation quality.

Audit your current KV cache memory usage and benchmark FP8 vs INT8 on your specific hardware to determine the optimal configuration for your deployment.

Related posts