五十一:KV cache¶
来源:http://mp.weixin.qq.com/s?__biz=MzYyNTk3Njg1NA==&mid=2247484669&idx=1&sn=60789d07c5c18d08c4b5637a8ad780fe&chksm=f01eb784c7693e92032a0c64e9afcb2220df02f822f2c7843a6b8628e2440765189b9e4559ec#rd
1. 学习范围¶
本日主题是 KV cache,重点是 KV cache 原理。 本日覆盖: - KV cache 的定义和动机。
-
Transformer attention 中 Q/K/V 的角色。
-
KV cache 在 Prefill 和 Decode 中的写入、读取和追加。
-
KV cache 显存公式。
-
MHA、MQA、GQA 对 KV cache 的影响。
-
缓存分配、碎片、分页、滑动窗口和量化。
-
StreamLLM、attention sinks 与流式长上下文。
-
KV cache 的常见失败模式和面试表达。
2. Attention 中的 Q/K/V¶
在 self-attention 中,每个 token 的 hidden state 会线性投影成 Query、Key、Value。 公式:
在自回归生成中,新 token 的 query 需要和所有历史 token 的 key/value 做 attention。历史 token 的 K/V 如果每步重复计算,会造成巨大浪费。3. KV cache 的基本定义¶
KV cache 是在推理时缓存历史 token 的 Key 和 Value 的机制。它保存每一层历史序列的 K/V,供后续 Decode step 直接读取。
没有 KV cache:
有 KV cache: KV cache 是现代 LLM 高效自回归推理的基础。4. Prefill 阶段的 KV cache¶
Prefill 处理完整 prompt,并一次性生成 prompt 中每个 token 的 K/V cache。 输入:
输出缓存: Prefill 后,Decode 可以从长度S 的缓存开始生成。
5. Decode 阶段的 KV cache¶
Decode 每步输入一个新 token,计算该 token 的 K/V,并追加到缓存末尾。
第 t 步:
6. KV cache 显存公式¶
单个请求的 KV cache 显存近似:
其中: -L:层数。
-
2:K 和 V 两份缓存。 -
B:batch size 或活跃序列数。 -
H_kv:KV heads 数。 -
T:缓存序列长度。 -
D:head dimension。 -
bytes:每个元素字节数,例如 fp16 为 2。
这个公式是面试高频点。
7. KV cache 与模型结构¶
不同 attention 结构影响 H_kv:
- MHA:每个 query head 都有对应 K/V head,H_kv = H。
-
MQA:所有 query head 共享一组 K/V,
H_kv = 1。 -
GQA:多个 query head 共享一组 K/V,
1 < H_kv < H。
MQA/GQA 的主要推理收益是显著降低 KV cache 显存和带宽压力。
8. KV cache 与 batch size¶
KV cache 与活跃序列数线性相关。并发越高,需要保存的 KV cache 越多。 推理服务中的 batch 不只是静态 batch,而是动态活跃请求集合。每个请求有不同 prompt 长度和生成长度,这让 KV cache 管理变复杂。
9. KV cache 与上下文长度¶
KV cache 与序列长度 T 线性相关。上下文越长,每个请求的缓存越大。
长上下文推理的压力:
- 初始 Prefill 产生大量 KV。
-
Decode 每步读取更长 KV。
-
并发能力下降。
-
更容易显存不足。
10. KV cache 与 Decode 性能¶
Decode 每步读取历史 KV cache,因此缓存布局和内存带宽影响很大。 瓶颈来源: - 大量 KV 读取。
-
不同序列长度造成不规则访问。
-
cache fragmentation。
-
动态分配开销。
-
GPU memory bandwidth 限制。
Decode 优化很大一部分就是 KV cache 优化。
11. 缓存预分配¶
简单做法是按最大上下文长度为每个请求预分配 KV cache。 优点: - 实现简单。
-
地址连续。
-
管理容易。
缺点: - 大量浪费。
-
短请求也占最大长度空间。
-
并发能力下降。
因此高性能推理系统通常需要更细粒度的缓存管理。
12. 缓存碎片¶
请求长度不同、结束时间不同,会造成 KV cache 碎片。碎片会让显存看似剩余很多,但没有足够连续空间分配新请求。 碎片问题类似操作系统内存管理,也是 PagedAttention 的重要动机。
13. Paged KV cache¶
Paged KV cache 把 KV cache 切成固定大小 block/page。一个序列的逻辑 KV 可以映射到多个非连续物理 block。 优势: - 减少预分配浪费。
-
减少碎片。
-
支持动态增长。
-
更容易共享 prefix。
-
提升并发。
vLLM 的 PagedAttention 就是代表性方案。
14. Sliding Window KV cache¶
Sliding window 只保留最近窗口内 token 的 KV cache。超出窗口的历史不再参与注意力。 收益: - 显存上限固定。
-
Decode 每步成本受控。
-
适合流式长文本。
风险: - 丢失远程依赖。
- 不适合需要全局记忆的任务。
15. Attention Sinks 与 StreamLLM¶
StreamLLM 提出 attention sinks 现象:模型在长流式推理中往往需要保留少量初始 token,配合最近窗口,可以维持较稳定生成。 策略可抽象为:
这为无限流式推理提供了一种缓存裁剪思路。16. Quantized KV cache¶
KV cache 量化把 K/V 从 fp16/bf16 降到 int8、fp8 或更低精度,以减少显存和带宽。 收益: - 更高并发。
-
更低显存。
-
Decode 带宽压力降低。
风险: - 精度损失。
-
模型质量下降。
-
实现复杂。
-
不同层和 head 敏感度不同。
17. Prefix Cache¶
Prefix cache 复用相同 prompt 前缀的 KV cache。适合系统 prompt、长模板、RAG 固定前缀等场景。 收益: - 减少重复 Prefill。
-
降低 TTFT。
-
降低计算成本。
挑战: - 前缀匹配。
-
cache 生命周期。
-
权限隔离。
-
多用户共享安全。
18. KV cache 与推理调度¶
调度器需要同时考虑计算资源和 KV cache 空间。 当 KV cache 空间不足时,即使 GPU 算力空闲,也无法接纳新请求。 调度策略需要考虑: - 每个请求已用 KV。
-
预计生成长度。
-
最大上下文长度。
-
是否可以抢占。
-
是否可以换出。
-
是否需要优先短请求。
19. KV cache 与显存估算案例¶
假设:
KV cache 约为: 这说明长上下文下 KV cache 很快成为关键显存成本。20. 常见失败模式¶
KV cache 相关失败包括: - 显存不足。
-
cache 泄漏。
-
batch 调度低效。
-
prefix cache 跨用户泄露。
-
滑动窗口导致远程信息丢失。
-
量化导致质量下降。
-
cache eviction 策略导致请求失败。
-
长尾请求占用大量缓存。
21. 面试表达要点¶
推荐表达:
KV cache 保存历史 token 的 K/V,避免 Decode 阶段重复计算历史。
它把计算问题转成显存和带宽问题。
显存与层数、KV head 数、序列长度、batch、head 维度和 dtype 线性相关。
22. 参考资料¶
-
Hugging Face KV cache documentation: https://huggingface.co/docs/transformers/main/en/kv_cache
-
KV cache 详解: https://zhuanlan.zhihu.com/p/685853516
-
KV cache 图解: https://zhuanlan.zhihu.com/p/662498827
-
StreamLLM: Efficient Streaming Language Models with Attention Sinks: https://arxiv.org/abs/2309.17453
-
vLLM PagedAttention documentation: https://docs.vllm.ai/en/stable/design/paged_attention.html
-
https://jishuzhan.net/article/1922454804413140993
预览时标签不可点<div class="