KV Cache 系统性学习指南

适用范围:大模型推理中的 KV Cache(计算机制、性能模型、存储布局、压缩方法与在线服务系统)。

文档目标:作为分阶段学习材料。完成后应能完成显存估算,说明主流推理系统中的 KV 管理方式,并对相关论文按优化类别进行归类。

0. 使用说明

本文将 KV Cache 作为独立专题,覆盖注意力计算、显存与吞吐模型、内核实现、压缩算法及在线推理系统。建议按阶段推进,并以各阶段验收标准作为完成判据。

阶段 内容 验收标准
1 计算机制 能够推导有/无 Cache 时单步 Decode 的 FLOPs 与访存量
2 性能模型 能够估算典型配置(如 7B/70B、8K/128K、FP16/INT8)下的 KV 显存占用
3 布局与内核 能够说明 PagedAttention、FlashDecoding 所解决的问题及其边界
4 压缩与近似 能够区分无损存储压缩、有损近似,以及注意力定义变更
5 服务系统 能够描述请求生命周期中 Cache 的创建、共享、换出与释放
6 模型结构 能够说明 GQA、MLA、线性注意力对 KV 存储形态的影响

各章末给出掌握要求与可选实验。不要求一次性通读;达到对应验收标准即可进入下一阶段。

1. 定义与作用

在自回归 Transformer 中,生成当前 token 需对已生成(及 prompt)序列计算注意力。该计算依赖历史 token 的 Key(K)Value(V)

若每一步对全部历史重新计算 K、V,计算复杂度随序列长度近似按平方增长。KV Cache 将已计算的 K、V 驻留于显存:后续步骤仅计算当前 token 的 Q、K、V,并与缓存中的历史 K、V 完成注意力。

定义: KV Cache 是注意力计算中已生成 token 的 Key、Value 的可复用存储,用于避免 Decode 阶段对历史状态的重复计算。

主要影响如下:

  • 时延: 长上下文与多轮对话中,Decode 不再重算历史 K/V,逐步时延显著下降。
  • 显存: Cache 规模随层数、KV 头数、序列长度与 batch 增长,通常构成推理显存的主要部分之一。
  • 后续优化空间: 量化、分页分配、前缀复用、滑动窗口等,均围绕降低 KV 的存储与带宽开销、提高系统吞吐展开。

2. 计算机制

2.1 Prefill 与 Decode

阶段 输入 KV 写入 计算特征
Prefill 完整 prompt 一次性输入 为 prompt 中各 token 写入 K/V 计算密度较高,主要影响 TTFT(首 token 时延)
Decode 每次一个或少量新 token 仅追加当前 token 的 K/V 通常为 memory-bound,主要影响 TPOT(每 token 时延)

Prefill 完成 KV 的初始填充;Decode 在读取已有 Cache 的同时追加新条目。Cache 的主要收益出现在 Decode 阶段。

2.2 Query、Key、Value

  • Q(Query): 当前 token 的查询向量。Decode 阶段通常仅计算当前 token 的 Q,一般不纳入 Cache。
  • K(Key): 历史 token 的键向量,用于匹配。写入 Cache。
  • V(Value): 历史 token 的值向量,用于加权聚合。写入 Cache。

注意力计算可写为:

1
2
score = softmax(Q @ K^T / sqrt(d))
out = score @ V

启用 Cache 时,K、V 由「历史缓存」与「当前步新计算的 K/V」拼接得到;Q 仅来自当前步。

2.3 张量形状

概念形状为:

1
K, V: [num_layers, num_kv_heads, seq_len, head_dim]

工程实现中通常按层分别存储,并引入 batch 或分页维度。须区分:

  • num_heads Query 头数
  • num_kv_heads Key/Value 头数
  • MHA: num_kv_heads = num_heads
  • GQA: num_kv_heads < num_heads(若干 Query 头共享一组 K/V)
  • MQA: num_kv_heads = 1
  • MLA: 以低秩或压缩潜变量表示 K/V,推理阶段进一步降低 Cache 体积

在相同序列长度下,KV 显存与 num_kv_heads 成正比。因此 GQA/MQA 已成为开源模型的常见配置。

2.4 位置编码(RoPE)与缓存内容

LLaMA 类模型普遍采用 RoPE。实现层面需明确:

  • Cache 中保存的是 旋转后的 K 还是 未旋转的 K(V 通常不施加旋转)。
  • 多轮续写、前缀复用与投机解码回滚时,位置编号须与写入时一致。
  • 位置外推(YaRN、NTK 等)改变旋转方式,并不取消 Cache,但影响长上下文可用性及窗口策略。

2.5 因果掩码

无 Cache 时,需对完整序列施加下三角因果掩码并重复计算。
启用 Cache 后,历史状态已按因果顺序写入;当前步仅需对区间 [0, current_len) 计算注意力。

实现中仍须处理 padding、变长 batch、分页块中的空洞,以及 chunked prefill 的局部因果约束。

2.6 掌握要求

  • 给出无 Cache / 有 Cache 时,单步 Decode 的 FLOPs 量级及其与 seq_len 的关系(线性或平方)。
  • 说明 Query 通常不进入 Cache 的原因。
  • 说明 GQA 降低 KV 存储的机制。

可选实验: 以单层注意力的最小实现对比「逐步重算全部 K/V」与「仅追加 Cache」,并记录各步矩阵乘尺寸。

3. 性能模型

Decode 阶段的逐步时延,往往受限于将历史 KV 自 HBM 反复读入计算单元,而非算术运算本身。

3.1 算力与带宽

  • Prefill: 序列较长、计算密集,更容易饱和 Tensor Core。
  • Decode: 单步计算量较小,但需读取完整历史 KV,通常表现为 memory-bound。

结合 Roofline 模型:短上下文下瓶颈可能仍在算力;序列延长后,瓶颈向内存带宽转移。

3.2 显存估算

在单一存储精度下,K 与 V 各占一份:

1
KV_bytes ≈ 2 * num_layers * num_kv_heads * head_dim * seq_len * batch * sizeof(dtype)

kv_hidden = num_kv_heads * head_dim 时,等价于:

1
KV_bytes ≈ 2 * num_layers * kv_hidden * seq_len * batch * sizeof(dtype)

说明:

  • 须使用 kv_heads,不可误用 Query 头数。
  • 采用 MLA、量化或其它压缩后,应按「实际缓存元素数量 × 每元素字节数」重新计算。
  • 上述结果仅为 KV 本身;模型权重、激活、CUDA Graph 及分配碎片另计。

数量级参考:

配置 说明
7B 量级、GQA、FP16、2K KV 相对权重量通常不占主导
70B 量级、128K 上下文、较大 batch KV 往往首先成为显存上限
FP16 → INT8(量化有效时) KV 体积约降至原来的 1/2
MHA → GQA(kv_heads 降至 1/8) KV 体积约降至原来的 1/8

3.3 Batch 与并发

增大 batch 可摊销权重读取开销,但 KV 占用随 batch 线性增长。在线服务中的典型约束顺序为:

  1. KV 显存限制最大并发;
  2. 内存带宽限制 Decode 逐步时延;
  3. Prefill 与 Decode 混合执行时争用算力与显存。

3.4 关键指标

指标 含义 与 KV 的关系
TTFT 首个输出 token 时延 主要由 Prefill 决定;前缀缓存命中时可显著下降
TPOT / ITL 后续每 token 时延 主要由 Decode 读取 KV 的带宽决定
Throughput 系统 tokens/s 由并发、调度及 KV 共享/分页共同决定
Max concurrency / Max context 可支撑的并发与上下文长度 直接受 KV 体积约束

3.5 掌握要求

给定 layerskv_headshead_dimdtypeseqbatch,估算 KV 显存,并判断 Decode 瓶颈更接近算力还是带宽。

可选实验: 固定模型,扫描 seq_len ∈ {1K, 8K, 32K, 128K},记录 TTFT、TPOT 与显存,并与估算公式对照。

4. 存储布局与内核实现

4.1 连续存储与分页

方案 优点 限制
max_seq 预留连续张量 实现简单,内核友好 变长序列浪费显存;预分配易产生碎片,并出现实际未用满即显存不足
PagedAttention(如 vLLM) 按 block 分配,类似操作系统分页 需维护 block table;内核需间接寻址

PagedAttention 的核心是 显存管理(碎片、预留与共享),并不改变注意力数学定义。不同请求及公共前缀可按 block 共享同一物理 KV。

4.2 Layout

常见布局包括 BHSDBSHD、按层拆分、K/V 交错存放等。布局影响:

  • 追加 token 时是否可顺序写入;
  • 注意力内核能否合并访存;
  • 量化、换出及跨设备搬运的实现复杂度。

不存在与内核及量化方案无关的「全局最优」布局,须与具体实现绑定评估。

4.3 写入、扩展与衔接

高频操作包括:

  • Prefill 完成整段写入;
  • Decode 每次追加 1 个 token(投机解码时可能为多个);
  • 超出当前 block 容量时分配新块;
  • Chunked prefill:将 prompt 分块计算,并按正确位置拼接 KV;
  • 抢占与恢复:换出后再换入时,位置映射须保持一致。

4.4 内核要点

  • FlashAttention: 减少注意力中间结果对 HBM 的读写。
  • FlashDecoding / split-K: 在序列长、batch 小的 Decode 场景下,对 K/V 分片并行计算后再归约。
  • 算子融合: 尽量减少 QKV 投影、RoPE、Cache 写入、注意力与输出投影之间的内核启动次数。
  • Warp specialization: 部分 warp 负责数据搬运,部分 warp 负责计算。

学习重点在于优化目标:降低 KV 的 HBM 读取量,并提高已读数据的计算复用。

4.5 存储精度与计算精度

常见做法是 Cache 以较低精度驻留(INT8 / FP8 / INT4),计算注意力时再反量化至较高精度。须分别记录:写入量化、驻留格式、计算格式。由于数值分布、RoPE 及 outlier,K 的量化难度通常高于 V。

4.6 掌握要求

说明 vLLM、SGLang、TensorRT-LLM 等系统维护 block table(或等价间接层)的原因。

建议阅读路径: FlashAttention / FlashDecoding → PagedAttention → 开源实现中 reshape_and_cacheflash_attn_with_kvcache 等接口的调用关系。

5. 压缩、稀疏与近似方法

阅读文献前应先分类,避免将不同性质的工作一律称为「压缩」。

类型 含义 代表方向
无损或近无损存储压缩 注意力公式不变,主要降低体积与带宽 KV 量化:KIVI、KVQuant、QServe 等
有损驱逐 / 稀疏 丢弃或合并部分历史 token 的 KV StreamingLLM(sink 与窗口)、H2O、SnapKV
结构或注意力定义变更 训练或结构上缩小 Cache,或改为固定状态 GQA、MLA、SWA、YOCO、线性注意力 / SSM

对任意论文,建议首先确认:

  1. 推理阶段注意力公式是否发生变化;
  2. 最坏情况下 Cache 是否仍随 seq_len 线性增长;
  3. 质量损失主要出现在短上下文、长上下文,还是特定任务(如检索、代码)。

5.1 量化

关注:K 与 V 是否独立量化;粒度(per-token / per-channel / 分组);outlier 与 RoPE 后的 K;反量化开销是否抵消带宽收益。

5.2 稀疏与驱逐

关注:保留策略(最近窗口、注意力权重较高的 token、sink token);驱逐发生在 Decode 过程中还是 Prefill 之后一次性完成;对远距离精确匹配任务(复制、长依赖)的影响。

StreamingLLM 的典型做法是保留序列起始处的若干 attention sink,并与最近窗口组合,稳定性通常优于朴素滑动窗口。

5.3 低秩、跨层共享与窗口注意力

  • MLA: 将 KV 映射至低维潜状态,以降低 Decode 缓存宽度。
  • 跨层共享: 并非每一层均保存完整 KV(如部分 YOCO / 跨层复用方案)。
  • Sliding Window Attention: 每层仅关注局部窗口,Cache 可按窗口上限封顶,常与若干全局层配合。

5.4 检索式长上下文

远距离历史不全部驻留 GPU Cache,而置于外部存储或检索系统,按需载入。此时 Cache 不再等价于模型已处理过的全部 token,属于系统与算法的结合方案。

5.5 掌握要求

能够将一篇 KV 相关论文归入量化、驱逐或结构变更,并指出质量与效率的折中发生在何处。

6. 在线推理系统中的 Cache

单请求计算正确仅是基础;多请求之间的共享与调度决定系统成本与服务质量。

6.1 Prefix / Prompt Cache

对相同系统提示、工具描述、RAG 固定前缀或共用模板,可复用已计算的 Prefill 结果。命中时 TTFT 可下降一个数量级,幅度取决于前缀占比。

约束包括:前缀须在 token 级完全一致(含特殊 token 与模板空白);索引结构(hash 或前缀树)的维护方式;命中后位置编码的衔接。

6.2 Radix / 前缀树(如 SGLang)

按 token 前缀将多请求 KV 组织为树,公共前缀在物理上仅保存一份。适用于树状采样、共享 system prompt 的高并发、分支对话及搜索式解码。

与 PagedAttention 的分工:分页解决块的分配;radix 解决哪些块可被共享。

6.3 多轮会话

多轮对话应优先在已有 Cache 上续写,避免每轮将完整历史作为新 prompt 重新 Prefill。须处理:历史截断或摘要导致的 Cache 失效;中间插入的工具结果与系统消息;用户回改历史内容后,须自分叉点起作废对应 KV。

6.4 换出(Offload)

数据路径一般为 HBM → 主机内存 → SSD。收益取决于:

  • PCIe / NVLink 带宽相对于重新 Prefill 的成本;
  • 换出粒度(整请求或远历史 block);
  • 换入是否位于 Decode 关键路径上。

可复用前缀宜优先保留于 GPU;访问频率极低的远历史再考虑换出。

6.5 调度

主题 与 KV 的关系
Chunked prefill 将长 prompt 分块,降低 Decode 饥饿;KV 按块写入
Prefill / Decode 分离(PD disaggregation) Prefill 节点向 Decode 节点传输 KV,网络载荷即 KV 体积
抢占 须支持 KV 换出或丢弃后重算;策略影响尾部时延
连续 batching 各请求 seq_len 不同,更依赖分页与 block table

6.6 投机解码与多 token 预测

草稿模型或 MTP 可能先行写入候选 token 的 K/V。校验失败时须将 Cache 回滚至分叉点,不得将未接受 token 的 KV 保留为历史状态。

6.7 多设备并行

  • Tensor Parallel: 注意力头被切分,各设备保存对应 KV;并发能力仍受单卡 HBM 限制。
  • Pipeline Parallel: 不同层位于不同设备,KV 随层分布。
  • PD 分离与多机: KV 成为网络载荷,可考虑量化后再传输,并结合层内并行切分。

6.8 掌握要求

能够描述如下生命周期:请求到达 → 查询前缀缓存 → 未命中则 Prefill、命中则跳过对应计算 → Decode 追加 → 结束释放或进入会话池 → 可能被量化、共享、换出或抢占。

7. 与训练及模型结构的关系

若结构采用 MHA 且窗口不受限,推理侧优化无法改变 KV 随序列长度线性增长这一基本事实。

方向 对 KV 的影响
GQA / MQA 减少 kv_heads
MLA 减少每 token 缓存宽度
窗口注意力 / 混合窗口 为 Cache 设置上限
线性注意力、SSM、RWKV、Mamba 及混合结构 Cache 转为固定大小状态,不再按 token 线性保存 K/V
长上下文训练与位置外推 决定 32K/128K/1M 等长度是否可用,以及 RoPE/Cache 的长度上限
MoE 专家权重不进入 KV;注意力层 KV 须单独核算。通信开销与显存占用分属不同预算

本章用于区分:所谓「长上下文能力」是将完整 128K KV 驻留 GPU,还是窗口、检索与压缩的组合结果。

8. 推荐学习顺序

建议按序完成。跳过性能估算直接阅读系统名词,容易停留在概念层面而无法做定量判断。

  1. 推导单步 Decode 的 FLOPs 及自 HBM 读取的字节数。
  2. 掌握 KV 显存公式,并用真实模型配置验算。
  3. 区分 MHA / GQA / MQA / MLA 对 Cache 形状的影响。
  4. 说明 FlashAttention / FlashDecoding 减少的访存类别。
  5. 说明 PagedAttention 如何处理变长序列、碎片与 block 共享。
  6. 说明前缀复用(Prompt Cache / RadixAttention)的命中条件与收益。
  7. 在量化、驱逐、MLA 中选择一条路径深入,避免并行铺开。
  8. 掌握服务侧要点:PD 分离、换出、连续 batching、投机解码回滚。
  9. 对照线性注意力 / SSM / 混合结构,判断 KV 是被压缩还是被状态替换。

9. 自测问题

可用于掌握程度检查。建议按「结论、机制、数量级或实例」作答。

  1. Decode 逐步时延较高,同时显存主要被 KV 占用,二者如何同时成立?
  2. GQA 成为常见配置的原因是什么?MLA 额外解决了哪一类开销?
  3. PagedAttention 优化的是显存管理还是注意力算法本身?
  4. Prefix cache 命中时,TTFT 为何可能下降一个数量级?
  5. 量化 KV 时,K 的难度通常高于 V 的原因是什么?
  6. 128K 上下文下,瓶颈更可能来自计算还是 KV 搬运?
  7. 连续 batching 中,按 max_seq 预分配连续 KV 为何容易在未真正用满时出现 OOM?
  8. 投机解码失败时,为何必须回滚 KV?
  9. PD 分离中网络传输的对象是什么?量化 KV 对该部署形态的意义何在?
  10. StreamingLLM 中的 sink token 针对何种失效模式?

10. 最小实验清单

不要求集群环境。单卡小模型即可用于建立数量级直觉。

实验 方法 观察项
显存随长度变化 固定 batch=1,增加 prompt 长度 显存是否近似线性增长,Decode 时延变化
显存随 batch 变化 固定长度,提高并发 先出现 OOM 还是先出现时延上升
前缀复用 两次请求共享较长 system prompt 第二次请求的 TTFT
量化 KV 在框架支持时启用 INT8/FP8 KV 显存、TPOT,以及简单问答与长复制任务质量
多轮续写与全量重算 同一对话的两种接口用法 Prefill 耗时差异

实验记录须包含:模型名称、kv_heads、dtype、seq、batch、推理框架,否则结果不可复现。

11. 术语表

术语 说明
KV Cache 已计算注意力 Key/Value 的缓存
Prefill 一次性处理 prompt 并填充 KV
Decode 逐 token 生成,读取并追加 KV
GQA/MQA 通过减少 K/V 头数降低 Cache 规模
MLA 以压缩潜状态表示 KV
PagedAttention 以分页块管理 KV 显存
Prefix / Radix Cache 跨请求共享公共前缀的 KV
FlashDecoding 面向 Decode 的注意力内核优化
PD disaggregation 将 Prefill 与 Decode 部署于不同节点
Attention sink 序列起始处需保留的少量 token,用于缓解窗口截断导致的稳定性问题

12. 可扩展方向

本文为学习大纲,而非论文综述。后续扩展建议每次只加深一章:

  • 实现: 对照 vLLM / SGLang 的 KV 分配路径与注意力内核调用链;
  • 文献: 按量化、驱逐、结构三类各选若干篇精读,记录问题、方法、公式是否变更及评测场景;
  • 服务: 前缀命中率、KV 传输量、PD 分离带宽预算。

13. 小结

  • Decode 依赖历史 K/V;Cache 以存储换取历史状态的免重复计算。
  • 主要代价为显存占用与 HBM 带宽;长上下文场景下二者通常主导成本与时延。
  • 工程上宜先处理布局与分页,再处理跨请求共享与调度,然后考虑量化与驱逐。
  • 结构层面可通过 GQA、MLA、窗口注意力或线性状态,从源头降低乃至替代随长度增长的 KV。
  • 评估任一项优化时,应明确其降低的是计算量、访存量、显存占用,还是跨请求重复 Prefill。