KV Cache 详解:为什么大模型推理那么吃显存
部署大模型时,一个常见的困惑是:模型权重明明只占了显存的一半,为什么并发稍微高一点、对话稍微长一点就报显存不足?答案通常是 KV Cache(键值缓存)。它是大模型推理中除权重之外最大的显存消耗者,并且随上下文长度和并发数线性增长。 理解 KV Cache,是做好推理部署和成本规划的基础。
KV Cache 是什么
大模型生成文本是一个 Token 接一个 Token 进行的。每生成一个新 Token,模型都要通过注意力机制“回顾”之前所有的 Token。在注意力计算中,每个 Token 都会生成 Key 和 Value 两组向量,原理见 Transformer 架构通俗讲解。
如果每次生成都重新计算之前所有 Token 的 Key 和 Value,计算量会随长度急剧增加。KV Cache 的做法是:把已经计算过的 Key 和 Value 保存下来,生成新 Token 时只计算新 Token 的部分,再与缓存拼接使用。 这是用显存换计算时间的经典策略。
显存占用如何估算
KV Cache 的大小大致与以下因素成正比:
- 层数:模型有多少层,每层都要缓存;
- 注意力头的配置:Key/Value 头的数量和每个头的维度;
- 序列长度:输入加上已生成的 Token 总数;
- 并发请求数:每个请求都有自己的缓存;
- 数值精度:16 位还是 8 位存储。
可以这样理解:每个 Token 在每一层都要占用一小块固定大小的缓存空间,总量就是“每 Token 每层的缓存大小 × 层数 × 总 Token 数 × 并发数”。对于中等规模的模型,单个请求在长上下文下的 KV Cache 可能达到数 GB,多个并发请求叠加后,很容易超过模型权重本身的显存占用。
这就是为什么长上下文和高并发会让显存需求急剧上升,也是长上下文推理昂贵的原因之一,参见上下文窗口的能力边界。
主流优化手段
1. 分组查询注意力(GQA)与多查询注意力(MQA)
标准多头注意力中,每个头都有独立的 Key 和 Value。MQA 让所有查询头共享一组 Key/Value,GQA 则让每组查询头共享一组 Key/Value。这直接把 KV Cache 缩小数倍,而效果损失很小。目前许多主流模型都采用了 GQA,这是模型架构层面的优化。
2. 缓存量化
把 KV Cache 从 16 位降低到 8 位甚至更低精度存储,显存占用相应减少。需要在目标任务上验证效果是否受影响,量化的通用原理见模型量化详解。
3. 分页管理
借鉴操作系统的内存分页思想,按需分配缓存块,避免预分配造成的浪费和碎片。这是 vLLM 等推理引擎的核心技术,详见 vLLM 推理服务入门。
4. 前缀缓存复用
多个请求共享相同的前缀(例如相同的系统提示词、相同的参考文档)时,只需计算和存储一次前缀部分的 KV Cache。很多 API 服务商提供的“提示缓存”折扣,背后就是这一原理。
5. 缓存卸载
把暂时不用的缓存从 GPU 显存转移到 CPU 内存甚至磁盘,需要时再加载回来。适合多轮对话中用户长时间未回复的场景,代价是重新加载时的延迟。
6. 稀疏与压缩方法
研究领域还在探索只保留重要 Token 的缓存、对缓存进行压缩等方法,以支持更长的上下文。这些方法在效果和通用性上仍在发展中。
对应用开发者的启示
- 控制上下文长度:不要无节制地累积对话历史和参考资料,按需裁剪和摘要;
- 固定前缀放在前面:把系统提示词等不变的内容放在请求开头,便于命中前缀缓存,降低成本和延迟,参见大模型 API 成本优化;
- 规划显存时预留缓存空间:自建推理时,不能只按权重大小选择 GPU,需要根据目标并发和上下文长度估算 KV Cache 需求,参见大模型推理 GPU 选型。
小结
KV Cache 用显存换取推理速度,是大模型推理不可缺少的机制,也是显存占用的主要来源之一。GQA、缓存量化、分页管理和前缀复用等技术从不同角度缓解了这一问题。理解 KV Cache 的增长规律,能帮助你更准确地规划硬件、控制成本,并设计出更高效的提示词结构。