ArcLibrary

KV Cache(推理性能的命门)

为什么长上下文越聊越慢、越聊越贵 —— 因为 KV cache 在不停长。

InferenceKVMemory
核心 · Key Idea

一句话:自回归生成时,前面已计算好的 K / V 矩阵会被缓存复用,不必每生成一个 token 重算前文。但 cache 随上下文线性增长,是长上下文推理的主要内存与带宽来源。

是什么#

生成第 N 个 token 时:

  • 只需要算新 token 自己的 Q/K/V;
  • 之前 N-1 个 token 的 K/V 从 cache 读
  • 用新 Q 与全部 K 做 attention。

没有 cache → 每个新 token 都重算全部 → 复杂度 O(N²) 每步 → 总 O(N³)。
有 cache → 每步 O(N) → 总 O(N²)。

打个比方#

打个比方 · Analogy

KV cache 像会议室的录音稿:来一个新发言(token)只需录新这一段,前面发言翻档案就行;不用让所有人再重说一遍

大小估算#

KV cache 字节数 ≈
   2 (K + V)
 × num_layers
 × num_kv_heads        // GQA / MQA 后的 KV head 数
 × head_dim
 × seq_len
 × dtype_bytes         // bf16 = 2, fp8 = 1, int4 = 0.5

LLaMA-3 70B、上下文 8K、bf16:

2 × 80 × 8 × 128 × 8192 × 2  ≈  2.7 GB

跑 batch 16 → 43 GB,只 KV cache 就要专门一张卡

关键概念#

Prefill / Decode前缀阶段 / 解码阶段
prefill 一次算所有 prompt(GPU 计算密集);decode 一次一个 token(带宽密集)。
PagedAttention分页缓存
vLLM 把 cache 切成 16-token 一页,避免长度不齐造成碎片。
Continuous Batching持续合批
新请求到了立刻插进 batch 而不是等批结束 —— 吞吐翻倍。
Prefix Cache前缀复用
system prompt 公用 → KV 复用,节省 prefill 时间。
KV 量化KV Quant
int8 / int4 KV,压缩长上下文显存(精度有限损失)。
Off-load下放
长上下文 KV 放 CPU / NVMe,按需 swap 回 GPU(慢但能撑)。

怎么工作#

实操要点#

  • 吞吐和延迟是两件事:prefill 慢 = 首 token 等待长(TTFT);decode 慢 = 每秒 token 数低(TPS)。优化点不同。
  • vLLM / TensorRT-LLM / SGLang 已经把 PagedAttention + Continuous Batching + Prefix Cache 这些做完,自己写推理一定打不过
  • 超长上下文 (>32k) KV cache 是主要瓶颈:考虑 KV 量化 / SWA(滑动窗口)/ RoPE 外推 + 局部+全局混合 attention。
  • system prompt 长:开 prefix cache 让 N 个用户复用同一份 KV。
  • 批量推理 OOM:调小 max_seq_len 或 max_num_seqs,不要无限合批。
  • 注意 batch=1 也省不了多少 KV:KV 大小 ∝ seq_len,跟 batch 无关。

易混点#

Prefill
一次性处理整个 prompt。
计算密集,能用大 batch。
Decode
每次一个 token。
带宽密集,**优化空间最大**。

延伸阅读#