跳转至

五十一: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 的常见失败模式和面试表达。

img

2. Attention 中的 Q/K/V

在 self-attention 中,每个 token 的 hidden state 会线性投影成 Query、Key、Value。 公式:

Q = X W_Q
K = X W_K
V = X W_V
Attention(Q,K,V) = softmax(QK^T / sqrt(d_head)) V
在自回归生成中,新 token 的 query 需要和所有历史 token 的 key/value 做 attention。历史 token 的 K/V 如果每步重复计算,会造成巨大浪费。

3. KV cache 的基本定义

KV cache 是在推理时缓存历史 token 的 Key 和 Value 的机制。它保存每一层历史序列的 K/V,供后续 Decode step 直接读取。 img

没有 KV cache:

每步都重新计算全部历史 token 的 K/V
有 KV cache:

只计算新 token 的 K/V,并追加到缓存
KV cache 是现代 LLM 高效自回归推理的基础。

img

img

img

img

4. Prefill 阶段的 KV cache

Prefill 处理完整 prompt,并一次性生成 prompt 中每个 token 的 K/V cache。 输入:

tokens: [B, S]
输出缓存:

K/V per layer: [B, H_kv, S, d_head]
Prefill 后,Decode 可以从长度 S 的缓存开始生成。

5. Decode 阶段的 KV cache

Decode 每步输入一个新 token,计算该 token 的 K/V,并追加到缓存末尾。 第 t 步:

old cache length = S + t - 1
new cache length = S + t
当前 query 会 attend 到完整历史 cache。随着生成继续,KV cache 线性增长。

6. KV cache 显存公式

单个请求的 KV cache 显存近似:

memory = L * 2 * B * H_kv * T * D * bytes
其中: - 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,配合最近窗口,可以维持较稳定生成。 策略可抽象为:

keep initial sink tokens + keep recent sliding window
这为无限流式推理提供了一种缓存裁剪思路。

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 与显存估算案例

假设:

L=32, H_kv=32, D=128, T=4096, bytes=2, B=1
KV cache 约为:

32 * 2 * 1 * 32 * 4096 * 128 * 2 bytes
= 2,147,483,648 bytes
约 2 GB
这说明长上下文下 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="