显存刺客 KV Cache:从算清账到撑起百万上下文
没有 KV Cache,大模型的自回归解码会沦为 的算力黑洞;有了 KV Cache,长上下文、高并发、多模态又会把 GPU 显存和带宽迅速榨干。
过去几年,行业围绕 KV Cache 走出了五条越来越清晰的路线:
- 系统层:PagedAttention、Continuous Batching、Prefix Caching、RadixAttention、CacheBlend、Mooncake,把 KV Cache 从一块临时张量变成可调度、可复用、可迁移的系统资源。
- 架构层:从 MQA、GQA 到 MLA,再到 CLA、NSA、CSA/HCA、Kimi Linear 这类混合注意力结构,直接从模型设计源头减少每个 token 必须缓存的状态。
- 算法层:StreamingLLM、、SnapKV、PyramidKV、RazorAttention、Quest、DMC 试图回答一个问题:哪些历史 token 真的值得继续留在 HBM 里?
- 量化层:KIVI、KVQuant、GEAR、SmoothKV、TurboQuant、Mixed-Precision KV 把问题从“存多少 token”推进到“每个向量到底要用多少 bit 存”。
- 存储层:ShadowKV、KVSwap、FlexGen、CXL Memory Pool、近内存计算把 KV Cache 推向 CPU、SSD、远端 DRAM,甚至专用内存设备。
导读
- 一句话:KV Cache 是大模型推理可用性的生命线,也是长上下文时代最硬的成本墙。
- 核心矛盾:它把重复计算变成缓存复用,但也把瓶颈从 FLOPs 转移到显存容量、HBM 带宽、跨节点传输和缓存一致性。
- 本文口径:成熟工程方案和前沿探索分开讲。PagedAttention、GQA、Prefix Caching、KV 量化这类已经进入主流框架;DeepSeek-V4 的 CSA/HCA、Kimi Linear 的 KDA+MLA、TurboQuant、CXL/NMP 等更像 2026 年正在打开的新方向。像“统一 KV 传输协议”这类生态想法,本文会按趋势讨论,不把它写成已经尘埃落定的事实标准。
引言
如果只看模型参数,很多人会误判长上下文推理的成本。以 70B 级模型为例,权重可以通过 FP8、INT4、MoE 激活稀疏等手段继续压;但上下文一旦拉到 128K、1M,真正线性增长、且每个请求都要动态保留的,往往是 KV Cache。
这也是为什么同样一张卡、同样一个模型,用朴素 HuggingFace 跑服务时吞吐上不去,而换成 vLLM / SGLang / TensorRT-LLM 之后,吞吐会出现数量级差异。差异不只来自 kernel,更来自 KV Cache 的组织方式:是否分页、是否能复用前缀、是否允许请求动态进出 batch、是否能把热 KV 和冷 KV 分层管理。
先给一个定义,避免后文混乱:
KV Cache:在自回归解码过程中,缓存每一层、每个注意力头的 Key 和 Value 向量,避免对历史 token 重复做 K/V 投影和注意力前缀计算。
Transformer 解码器每生成一个 token,都要让当前 Query 与历史全部 Key/Value 做注意力。如果不缓存,第 步会重新计算前 个 token 的 K、V;上下文长度变长后,这种重复计算会迅速失控。
所以 KV Cache 不是“可选优化”,而是今天 LLM 服务可用性的底座。
但它也不是免费午餐。它省下了重复计算,却把压力转移到四个地方:
- 容量:上下文越长、并发越高,KV Cache 越容易直接超过 VRAM。
- 带宽:Decode 每步都要读历史 K/V,长序列下很容易 Memory-bound。
- 碎片:在线服务里请求长度长尾分布明显,连续预分配会浪费大量显存。
- 复用:RAG、Agent、多轮对话里有大量重复前缀,不复用就会重复 Prefill、重复存储。
这就是 KV Cache 的核心矛盾:
没有它,LLM 慢到不可用;有了它,上下文一长,显存和带宽就会被撑爆。
一、KV Cache 到底在缓存什么
1.1 为什么不缓存就会爆炸
现代大语言模型的推理遵循自回归范式:每次只生成一个 token,将其追加到上下文后,再预测下一个。
设当前序列为 ,第 步要预测第 个 token,单层 Decoder Attention 可写成:
问题在于:Query 永远只有当前 token,而 Key/Value 会随着上下文长度线性增长。
如果采用最朴素的实现方式,每一步都把长度为 的前缀重新跑一遍 forward,那么:
- 第 步单层 Attention 计算大致是 。
- 从 到 全部累加,总代价接近:
长文本生成如果不做缓存,本质上就是在重复为同一段历史付费。
1.2 KV Cache 的本质:只算新增 token
KV Cache 的做法很直接:历史 token 的 K、V 只计算一次,后续步骤直接复用。
在每一层 Attention 中维护两个缓存张量 和 。当第 个 token 到来时:
- 仅对当前 token 计算:
- 将它们追加到缓存:
- 用当前 Query 与完整缓存做注意力。
这样之后,历史 token 的 K/V 投影只会发生一次。Decode 阶段每一步的主要成本,从“重新计算整段前缀”变成“读取并使用已有缓存”。
常见误区:FlashAttention 和 KV Cache 不是一回事
- FlashAttention 主要解决 Prefill 阶段 Attention 矩阵 的显存物化问题,通过 tiling 避免把完整 attention matrix 写入 HBM。
- KV Cache 主要解决 Decode 阶段重复计算历史 K/V 的问题。
- 两者经常同时出现,但不是替代关系。
1.3 先算一笔账:KV Cache 到底占多少显存
对单个请求而言,如果模型有 层、每层有 个 KV heads、每个 head 维度为 、上下文长度为 ,则 KV Cache 近似为:
其中前面的 分别对应 Key 和 Value。若使用 FP16 或 BF16,则 bytes。
例子:LLaMA-2-7B 手算
LLaMA-2-7B 的典型参数为:
- 层数
- KV heads (标准 MHA)
- FP16(2 bytes)
当上下文长度 时:
如果拉到 128K,上下文近似放大 4 倍:
也就是说,7B 模型权重大约十几 GB,但 128K 的 KV Cache 可以比权重还大得多。
主流结构对比
| 模型/结构 | 层数 L | KV heads / 结构 | 32K token | 128K token | |
|---|---|---|---|---|---|
| LLaMA-2-7B | 32 | 32(MHA) | 128 | ~16 GB | ~64 GB |
| LLaMA-3-8B | 32 | 8(GQA) | 128 | ~4 GB | ~16 GB |
| LLaMA-3-70B | 80 | 8(GQA) | 128 | ~10 GB | ~40 GB |
| DeepSeek-V2 | 60 | MLA | - | ~2.1 GB | ~8.2 GB |
工程上别忘了两件事
- 上面的公式是单请求视角。进入服务化场景后,还要考虑并发请求数、batch、beam、speculative decoding 分支等因素。
- 真正上线时,显存还要留给权重、激活、workspace、通信 buffer、CUDA graph、碎片冗余,所以可用窗口通常比理论值更紧。
1.4 三个基础工程难题
把公式算明白后,KV Cache 的工程麻烦就很清楚了:
| 挑战 | 本质问题 | 常见解法 |
|---|---|---|
| 显存不够 | 长上下文或高并发下,KV Cache 超过 GPU VRAM | GQA/MLA、KV 量化、Token 驱逐、CPU/SSD Offloading |
| 内存碎片 | 请求长度差异大,连续预分配造成浪费 | PagedAttention、Block Pool、Continuous Batching |
| 重复缓存 | 很多请求共享前缀,但各自重复 Prefill 和存储 | Prefix Caching、RadixAttention、CacheBlend、共享 KV Store |
这三类问题对应三种不同目标:
- 容量优化:让更长上下文或更多请求放得下。
- 吞吐优化:让 GPU 少等内存、少浪费 padding、少做重复计算。
- 复用优化:让系统把相同前缀当作公共资产,而不是每个请求重算一遍。
二、系统层:先把 KV Cache 管好
显存大不等于服务快。KV Cache 如果管得不好,GPU 仍然会长期低利用率。
2.1 连续预分配为什么浪费
早期推理框架常见做法,是为每个请求按最大长度预分配一整段连续显存。这种实现简单,但在线服务里很容易被请求长度分布击穿。
典型问题有两个:
- 内部碎片:给请求预留 4096 token 空间,结果它只生成 200 token,剩下空间被浪费。
- 外部碎片:不同长度请求交错分配和释放,在 HBM 中留下很多不连续空洞,导致总空闲显存够,但申请不到连续大块。
对 LLM 服务来说,这不是小问题。因为用户请求长度天然长尾,RAG 文档、多轮历史、Agent trace 都会让同一个 batch 里的序列长度差异非常大。
2.2 PagedAttention:像操作系统一样分页
vLLM 的核心创新之一,是把 KV Cache 从“连续大块内存”改成固定大小 block 的分页系统。
它的基本做法是:
- 把每个请求的 KV Cache 切成固定大小 block,例如 16 token 一块。
- 物理上这些 block 不要求连续。
- 用 block table 维护“逻辑 token 位置 -> 物理 block 地址”的映射。
这和操作系统里的虚拟内存分页是同一种思路。
直接收益有三点:
- 碎片下降:内部碎片只会出现在最后一个 block,外部碎片因为 block 定长而基本被消灭。
- 共享更自然:多个请求可以共享相同物理 block,通过引用计数管理生命周期。
- 调度更灵活:请求可以随时进入或离开 batch,不必为了连续内存整理付出额外成本。
PagedAttention 的真正价值不只是“省显存”,而是让更多请求能稳定驻留在 GPU 上,从而把吞吐拉起来。
2.3 Continuous Batching:让请求按 token 粒度流动
KV Cache 管理和 batching 是绑在一起的。
传统 static batching 会等一个 batch 里的所有请求一起开始、一起结束。问题是生成长度不可预测,短请求结束后会留下 padding 浪费,长请求又会拖住整个 batch。
Continuous Batching 的思路是按 decode iteration 调度:
- 每个生成步都可以插入新请求。
- 已结束请求马上释放资源。
- 当前活跃请求共享同一次 decode kernel。
这让 KV Cache block 的分配和释放变成动态过程,也解释了为什么 PagedAttention、block pool、iteration-level scheduling 通常要一起出现。
2.4 Prefix Caching / RadixAttention:别重复缓存相同前缀
在 RAG、AI 客服、代码助手、多轮 Agent 中,大量请求其实共享同一段前缀:
- 同一个 system prompt
- 同一个工具说明
- 同一批 RAG 文档 chunk
- 同一段长对话历史
如果每个请求都重新 Prefill,再各自存一份 KV Cache,计算和显存都会被重复消耗。
SGLang 的 RadixAttention 把这件事做成全局共享缓存:
- 用 Radix Tree 维护全局前缀索引。
- 新请求到来时做最长前缀匹配。
- 命中的前缀直接复用已有 KV Cache。
- 只对未命中的后缀继续 Prefill。
当前缀命中率足够高时,这种优化往往比“单纯换更强 GPU”更划算。它优化的不是单次 attention kernel,而是整个服务流量的重复结构。
2.5 CacheBlend:从完全命中走向部分复用
Prefix Caching 有一个隐含限制:它最擅长处理完全相同的前缀。但真实业务里,经常是“多数内容相同,局部有修改”:
- RAG 文档只更新了一小段。
- 用户在长 prompt 中改了几句话。
- Agent trace 中某个工具结果不同,但上下文结构大体一致。
CacheBlend 的思路是:不要因为局部变化就把整个前缀全部重算,而是只重算受影响边界附近的 token,并让未受影响的缓存继续复用。
这背后的关键判断是:局部编辑对 attention 状态的影响会传播,但传播范围通常可估计。工程上如果能把“重算区域”控制住,就能把前缀复用从 exact match 推向 near match。
2.6 Chunked Prefill:不要让超长输入霸占 GPU
长上下文请求通常分成两个阶段:
- Prefill:把整段输入编码成 KV Cache,算力消耗高。
- Decode:逐 token 生成,访存和调度更敏感。
如果一个超长 Prefill 一次性跑完,它会长时间占住 GPU,导致其他正在 decode 的请求 TTFT 和 TPOT 抖动。
Chunked Prefill 的做法是把超长输入切成小块,例如每次 512、1024、2048 token,与 Decode batch 交错执行。这样做的目标不是改变总计算量,而是改善在线服务的排队和交互延迟。
2.7 Mooncake:把 Prefill 和 Decode 拆成系统架构
当规模继续放大时,Prefill 和 Decode 混部会越来越别扭:
- Prefill 更吃矩阵计算和大 batch。
- Decode 更吃 KV 读取、调度和低延迟。
- 两者对硬件、网络、缓存复用的偏好都不一样。
Mooncake 这类 KVCache-centric 架构把问题从单机推理变成分布式系统问题:
- Prefill 节点专心处理长输入。
- Decode 节点专心生成。
- 中间通过 Transfer Engine / KV Store 迁移和复用 KV Cache。
- 路由器尽量把请求发到前缀命中率更高的节点。
这里最重要的转变是:KV Cache 不再只是某个 GPU 进程里的临时状态,而是可以跨实例调度的缓存资源。
2.8 统一 KV 传输层:趋势明确,标准未定
HTML 草稿里提到了 KVT(KV Cache Transfer Protocol)这种“Prefill once, Decode anywhere”的想法。这个方向非常合理,但写作时需要谨慎:截至 2026-05-13,更稳妥的表述不是“某个 KVT 标准已经统一业界”,而是:
KV Cache 正在需要一个跨框架、跨节点、跨压缩格式的传输层。
这个传输层至少要描述:
- Tensor shape、层号、head layout、position encoding 状态。
- dtype、量化方式、scale、zero-point、压缩 header。
- block 粒度、连续/分页映射、prefix hash。
- GPU-to-GPU、GPU-to-CPU、RDMA、CXL、NVMe 等传输路径。
- 不同框架之间的 layout 翻译,例如 vLLM、SGLang、TensorRT-LLM。
长期看,这件事很像“LLM 推理时代的缓存协议”。短期看,它更可能先以 Mooncake Transfer Engine、TensorRT-LLM KV block reuse、vLLM prefix caching、分布式 KV store 等具体工程能力的形式出现,而不是一夜之间变成完全统一的标准。
这一章的结论
如果问题是“显存明明不少,但吞吐低、TTFT 抖、GPU 利用率差”,第一优先级通常不是改模型,而是把 KV Cache 的分页、调度、前缀复用和 Prefill/Decode 资源隔离做好。
三、架构层:从源头减少每个 token 的缓存
KV Cache 大小正比于 KV heads 数量和每个 token 的缓存维度。系统层是在“已经生成的 KV”上做管理,架构层则更直接:让模型一开始就少产生 KV。
3.1 标准 MHA 为什么最费缓存
标准 Multi-Head Attention(MHA)里,每个注意力头都有独立的 K/V 投影矩阵。每生成一个 token,每一层、每一个 head 都要额外存一份 K 和 V。
单 token 增量为:
所以只要 很大,缓存就会线性膨胀。
3.2 MQA:极致省缓存,但质量风险高
MQA(Multi-Query Attention)的思路很激进:所有 Query heads 共享同一组 Key/Value。
如果原本有 32 个 heads,现在变成 1 个 KV head,则 KV Cache 理论上接近原来的 。
它的优点很明显:
- 显存占用大幅下降。
- Decode 阶段读取 K/V 的带宽压力更低。
问题也同样明显:
- 单个 KV head 容量有限,容易成为表达瓶颈。
- 长上下文、复杂推理、多事实检索任务上质量更敏感。
- 对通用大模型来说,压缩过于激进。
所以 MQA 更像是极限压缩路线,而不是今天通用旗舰模型的主流默认选择。
3.3 GQA:当前最务实的工业折中
GQA(Grouped-Query Attention)介于 MHA 和 MQA 之间。它把 Query heads 分组,每组共享一份 K/V。
| 配置 | Query heads | KV heads | KV Cache 相对 MHA | 代表模型 |
|---|---|---|---|---|
| MHA | 32 | 32 | 100% | 早期 GPT / LLaMA-2 7B |
| GQA-8 | 32 | 8 | 25% | LLaMA-3、Qwen2 |
| GQA-4 | 32 | 4 | 12.5% | Mistral-7B |
| MQA | 32 | 1 | 3.1% | PaLM、Falcon |
GQA 的价值在于:
- 比 MHA 明显省缓存。
- 比 MQA 稳定。
- 对训练、推理框架、kernel 生态都比较友好。
如果你在部署已有开源模型,GQA 往往已经是默认收益。你不一定需要主动“上 GQA”,但你必须知道模型的 KV heads 配置,因为它直接决定服务成本。
3.4 MLA:DeepSeek 路线为什么省
MLA(Multi-head Latent Attention)把 KV 压缩推进到架构内部。它不是简单减少 KV heads,而是把 K/V 共同投影到低维 latent 表示中,只缓存低维状态,再在计算时恢复需要的表示。
可以粗略理解为:
推理时不再直接缓存完整多头 K/V,而是缓存低维 ,并把 RoPE 相关的位置信息单独处理,避免位置编码和低秩压缩冲突。
MLA 的优势是:
- 从模型设计层面减少 KV Cache。
- 不依赖推理时驱逐历史 token。
- 对长上下文和高并发成本非常友好。
代价也很明确:
- 训练和实现复杂度更高。
- kernel、量化、框架适配都要围绕新结构做。
- 对已有 MHA/GQA 模型很难事后无痛改造。
3.5 CLA / MiniCache:层与层之间也有冗余
除了 head 维度,层维度也存在冗余。相邻层的 K/V 表示往往高度相关,因此有人开始尝试跨层共享或合并 KV。
代表思路包括:
- CLA(Cross-Layer Attention):让相邻层共享 KV Cache,直接减少层维缓存。
- MiniCache:用插值或合并方法,把相邻层 KV 表示压成共享表示。
这类方法的直觉是对的:Transformer 每层不是完全独立的信息空间,尤其在相邻层之间,K/V 分布可能足够接近。
但工程上它比 GQA/MLA 更敏感,因为它改变的是层间信息流。它更适合在训练或系统评估中一起考虑,而不是作为“随手打开的推理开关”。
3.6 NSA 与混合稀疏注意力:不是所有 token 都要全量注意
Native Sparse Attention(NSA)这类路线更进一步:不再先训练全量注意力、推理时再裁剪,而是让稀疏结构成为模型原生能力。
典型设计会把注意力拆成几条路径:
- 压缩路径:把长序列按 block 聚合,获得低成本全局视野。
- 选择路径:按 query 选择最相关的 block 或 token。
- 滑动窗口路径:保留最近局部细节。
它和后文的 KV 驱逐有本质差异:后者是 post-hoc,有损地删缓存;NSA 这类方法是训练时就让模型学会在稀疏结构中工作。
3.7 DeepSeek-V4 CSA/HCA:百万上下文的混合压缩思路
截至 2026-05-13,DeepSeek-V4 的公开材料把长上下文效率提升集中在 CSA/HCA 混合注意力上:
- CSA(Compressed Sparse Attention):把多个 KV token 压成一个条目,再通过索引器做 top-k 稀疏选择,并配合滑动窗口保留局部细节。
- HCA(Heavily Compressed Attention):更激进地压缩长程历史,对压缩流做更密集的注意力。
- mHC(Manifold-Constrained Hyper-Connections):从残差连接稳定性上支持更深、更长上下文的信号传播。
这条路线的意义不是“又一个 KV 量化技巧”,而是把百万上下文的成本问题从推理补丁提升到模型结构本身:模型训练时就接受压缩历史、稀疏检索和局部窗口的组合。
如果 MLA 是“低秩 latent 缓存”,CSA/HCA 更像是“压缩后的长程记忆 + 稀疏检索 + 局部精细窗口”的混合结构。
3.8 Kimi Linear:线性注意力和 MLA 的混合路线
Kimi Linear 的公开仓库把重点放在 KDA(Kimi Delta Attention)和 MLA 的 3:1 混合架构上:
- KDA 负责更高效的线性/递归式记忆。
- MLA 负责周期性地重新对齐全局依赖。
- 这种混合结构在 1M 上下文下把 KV 缓存需求压低,同时提高 decode throughput。
它传递出的信号很重要:未来长上下文模型未必会在“全量 attention vs 线性 attention”之间二选一,而更可能是混合结构。
这一章的结论
- 部署已有模型:优先理解它是 MHA、GQA、MLA 还是新混合结构。
- 新训模型:GQA 是成熟基线,MLA/CSA/HCA/KDA+MLA 是长上下文成本优化的前沿方向。
- 不要把所有 KV 压缩都放到推理阶段解决。很多问题在模型架构阶段解决,收益更干净。
四、算法层:推理时扔掉或合并“不重要”的 KV
如果模型结构已经定了,系统层也管好了,KV Cache 仍然太大怎么办?
答案是:推理时做有损压缩。
核心问题变成:
哪些历史 token 必须保留,哪些可以删、合并、降精度或变成摘要?
4.1 两类通常不能轻易删的 token
研究和工程实践里反复出现两类关键 token:
- Heavy Hitters:长期获得较高 attention 权重的语义关键 token。
- Attention Sink:序列开头少量特殊 token,例如
<BOS>,它们在 softmax 归一化中承担稳定作用。
这解释了为什么很多 KV 驱逐方法不会随机删 token,而是至少保留:
- 开头少量 sink token。
- 最近窗口。
- 历史上 attention 分数高的 token。
- 某些 retrieval heads 对应的全局历史。
4.2 StreamingLLM:保留 sink + 最近窗口
StreamingLLM 的策略非常简单:
- 保留开头少量 sink token。
- 保留最近窗口。
- 中间历史大量丢弃。
它的优势是显存近似 ,适合无限流式对话、虚拟角色、实时语音转写这类“最近上下文最重要”的场景。
但它不适合:
- 长文档问答。
- 代码库检索。
- 合同审查。
- 需要回看中间某个细节的 Agent trace。
因为中间历史一旦丢了,模型就真的无法精确回忆。
4.3 / SnapKV:保留 Heavy Hitters
的思路是累计 attention 分数,优先保留长期重要的 heavy hitters,再保留最近窗口。
SnapKV 则更多利用 Prefill 阶段的 attention 模式,提前预测哪些历史 KV 会在后续 decode 中被关注。
这类方法比纯滑窗更聪明,因为它承认“远处也可能有重要 token”。但它仍然是有损方法,关键风险在于:
- 新 token 尚未积累足够分数时可能被误删。
- Attention 分数不一定等价于任务真实重要性。
- NIAH(Needle In A Haystack)这类任务里,关键 token 可能只有在特定 query 下才变重要。
4.4 PyramidKV:不同层给不同预算
PyramidKV 的观察是:不同层的 attention 分布不一样。
- 底层更偏局部和细节,attention 更分散,可能需要保留更多 token。
- 高层更偏语义和全局,attention 更集中,可以用更少 token。
因此它按层分配不同 KV 预算,而不是所有层一刀切。这比固定比例驱逐更合理,因为 KV Cache 的“重要性”并不只和 token 有关,也和层有关。
4.5 RazorAttention:不是所有 head 都负责检索
RazorAttention 从 head 维度切入:有些 heads 是 retrieval heads,负责远距离检索;有些 heads 更偏局部模式或格式稳定。
因此可以:
- 对 retrieval heads 保留更多全局历史。
- 对 non-retrieval heads 只保留最近窗口或压缩摘要。
这个思路很工程友好,因为它避免了“所有 head 对所有 token 同样处理”的粗暴策略。
4.6 Quest / DMC:从删除走向查询感知和摘要
两条更细的路线值得单独拎出来。
Quest 的核心是 query-aware:不同 query 需要的历史 KV 子集不同,因此可以为每个 query 动态选择相关 block,而不是提前给所有 token 一个静态重要性分数。
DMC(Dynamic Memory Compression) 则不是简单丢弃 token,而是把多个 token 合并成固定大小摘要。它更像是在 KV Cache 里做在线记忆压缩:决定当前 token 是追加为新槽位,还是合并进已有槽位。
这两类方法的方向更接近未来:长上下文不是只靠“删不删”,而是要在查询时动态决定“读哪段、以什么精度读、是否读摘要”。
4.7 多模态:视觉 token 会把问题再放大
多模态场景下,KV Cache 的压力会更大。原因很简单:视觉 token 数量非常夸张。
一个高分辨率图片可能带来上千个视觉 token;多图、多帧视频、屏幕录制、Agent 视觉轨迹会迅速把上下文推到数十万甚至百万 token。
因此 VLM 里的 KV 压缩往往要结合视觉结构:
- 合并相邻相似 patch。
- 删除低显著性背景 token。
- 对视频帧做跨帧 token merging。
- 在文本 query 到来后,只激活相关视觉 block。
这和文本 KV 驱逐不同。文本里 token 的语义离散性更强;视觉里空间相似性和时间冗余更明显,所以压缩策略也应该更像视觉系统,而不是简单套用文本 heavy hitter。
4.8 驱逐方法的本质权衡
KV 驱逐和合并类方法的优势很清楚:
- 不必改模型权重。
- 对超长上下文很有效。
- 可以和 PagedAttention、量化、Offloading 叠加。
但它有一个不能回避的事实:
这是有损压缩。
下面这些任务要特别谨慎:
- 合同审查。
- 代码库检索。
- 长链路事实问答。
- 多轮 Agent 需要回忆早期工具输出。
- 安全对齐依赖特定 prompt 片段的场景。
结论不要记反:驱逐不是免费午餐,而是用精度和可解释风险换显存。能不能用,最终要看真实业务集回归,而不是只看通用 perplexity。
五、量化层:每个 KV 向量到底要用多少 bit
驱逐是“少存一些 token”,量化是“每个 token 少存一些 bit”。两者互补,也经常叠加。
5.1 KV 量化和权重量化不是一回事
权重量化面对的是相对静态的参数矩阵;KV Cache 面对的是在线生成出来的动态激活。
它有几个特点:
- 分布随层、head、token、position 变化。
- Key 和 Value 的异常值位置不同。
- RoPE 会改变 Key 的数值分布。
- Decode 时量化/反量化开销会直接影响 TPOT。
所以不能简单把权重量化方法搬过来。
5.2 Key 和 Value 应该区别对待
很多 KV 量化工作都观察到:
- Key Cache:异常值更容易集中在 channel 维,更适合 per-channel 量化。
- Value Cache:尺度变化更容易和 token 相关,更适合 per-token 量化。
KIVI 的经典价值就在这里:它把 K 和 V 的分布差异明确建模,而不是用同一种粒度处理两者。
5.3 KIVI / KVQuant:系统化 KV 量化的起点
KIVI 的核心做法是:
- Key 用 per-channel 量化。
- Value 用 per-token 量化。
- 最近一小段 token 保持高精度。
KVQuant 则沿着更系统的校准和低比特方向推进,试图把 KV Cache 压到 4-bit 甚至更低。
这些方法奠定了 KV 量化的基础问题意识:KV Cache 不是简单 tensor,不能只按普通 activation quantization 处理。
5.4 GEAR / SmoothKV:量化误差也可以被修正和迁移
当 bit 数继续降低,量化误差会迅速变成主要问题。
GEAR 的思路是:主 KV 用低比特量化,同时额外保存低秩残差修正。它承认低比特一定会丢信息,但用很小的额外存储把关键误差补回来。
SmoothKV 的思路是:通过等价变换把异常值从更难量化的位置迁移到更容易承受的位置,平滑 K/V 的分布。
这类方法说明,KV 量化不只是“把 FP16 round 到 INT4”,而是围绕 attention 内积稳定性做数值设计。
5.5 TurboQuant:从标量量化走向向量几何
TurboQuant 的思路更像向量量化:通过随机旋转让向量坐标分布更集中,再用量化方法控制内积估计偏差,并通过 QJL residual 做校正。
它对 KV Cache 的意义在于:
- 注意力依赖的是 Query-Key 内积,不只是单个坐标误差。
- 如果量化能更好保留向量几何结构,低比特下的质量损失就可能更小。
- 训练无关、在线友好的量化方法,才更容易被大规模 serving 接受。
截至 2026 年公开材料,TurboQuant 已经把讨论推到 3.5 bit 近似质量中性、2.5 bit 边际退化这一层级。它不是简单替代 KIVI,而是把 KV 量化从“异常值处理”推进到“几何结构保持”。
5.6 Mixed-Precision KV:重要的 token 用高精度
不是所有 KV 都需要同样 bit 数。
更自然的策略是:
- 高 attention、高风险、近窗口 token 用 FP16 / BF16。
- 中等重要 token 用 INT4。
- 低重要 token 用 INT2 / 2.5-bit / 3-bit。
这就是 Mixed-Precision KV 的核心直觉。它把驱逐和量化连在一起:不一定非要删掉低重要 token,也可以把它们降精度。
5.7 量化最适合什么场景
相较驱逐,量化有一个明显优势:信息还在,只是表达更粗糙。
因此它更适合:
- 不能轻易丢 token 的长文档。
- 代码、数学、事实检索这类需要保留全局内容的任务。
- 显存不够,但可以接受少量数值误差的服务。
主要风险是:
- 极低比特下,数学、代码、检索会比闲聊更敏感。
- 量化方案和模型结构耦合,例如 MLA / CSA / HCA 的缓存分布不能简单照搬 MHA/GQA 经验。
- 如果反量化 kernel 不够好,省下的显存可能被额外延迟抵消。
六、Offloading:GPU 放不下时,往外搬
如果系统管理、架构压缩、驱逐、量化都不够,那就只能把 KV Cache 从 HBM 往外搬。
6.1 三层存储的基本差异
| 存储层 | 典型容量 | 典型带宽 | 访问延迟 | 适合什么 |
|---|---|---|---|---|
| GPU HBM | 80 GB - 192 GB | TB/s 级 | ns 级 | 热 KV、低延迟 decode |
| CPU DRAM | 256 GB - TB 级 | 数十到数百 GB/s | us 级 | 冷 KV、长文档、批处理 |
| NVMe SSD | TB - PB 级 | GB/s 级 | 数十 us 以上 | 极冷 KV、离线批处理、端侧兜底 |
容量越来越大,但带宽和延迟会急剧变差。因此 Offloading 的关键不是“能不能放下”,而是“搬回来时会不会把 decode 卡死”。
6.2 ShadowKV:GPU 上保留影子索引
ShadowKV 的典型思路是:
- GPU 端保留压缩后的 Key 或索引结构。
- 完整 Value 放在 CPU DRAM。
- Decode 时先在 GPU 上判断需要哪些历史位置。
- 只把 top-k 相关 Value 拉回 GPU。
它利用了注意力计算的分工:打分主要依赖 Key,加权输出才需要 Value。只要能在 GPU 上用压缩 K 找到候选,就不必把完整 V 一直放在 HBM。
6.3 KVSwap / FlexGen:用 SSD 和调度换容量
KVSwap 更偏端侧和容量扩展:把冷 KV 换到 NVMe SSD,通过异步预取和批量写入降低 stall。
FlexGen 则更偏离线批处理:把权重、激活、KV 在 GPU、CPU、SSD 之间做整体调度,用吞吐换延迟。
这类方案适合:
- 离线长文档处理。
- 边缘设备或消费级显卡。
- 对交互延迟不敏感的 batch 任务。
不适合:
- 强低延迟对话。
- 高频短请求在线服务。
- 对 TPOT 抖动极敏感的场景。
6.4 CXL Memory Pool:容量墙可能被硬件改写
CXL 的意义在于把远端 DRAM 变成更接近设备可访问内存的资源池。对 KV Cache 来说,这可能改变今天 GPU HBM / CPU DRAM / SSD 的分层边界。
如果 GPU 能以更高带宽、更低软件开销访问 TB 级远端内存,那么一些原本复杂的软件 offloading 策略会重新排序。
但这不意味着 KV Cache 问题消失。硬件把容量墙后移后,新的瓶颈可能变成:
- 远端内存访问延迟。
- 跨设备一致性。
- 缓存热度预测。
- 多租户隔离和带宽公平性。
6.5 Near-Memory KV Processing:把 QK 打分推到内存侧
如果 KV 太大,搬数据本身就是问题。那么另一个方向是:不要把所有 KV 搬回 GPU,而是把部分计算推到内存侧。
Near-Memory KV Processing 的直觉是:
- 在 CXL memory device 或近内存设备上执行 QK 打分、top-k 选择。
- 只把最相关的 Value 或 block 传回 GPU。
- 用算力贴近数据,减少大规模 KV 回传。
这还处在更早期,但方向很清楚:当 KV Cache 变成主要数据资产后,推理系统会越来越像“围绕 KV 的存储计算协同系统”。
七、新问题:压缩不是终点
KV Cache 越被压缩,新的问题越明显。
7.1 Speculative Decoding 会制造分支 KV
Speculative Decoding 用小模型先生成多个候选 token,再由大模型批量验证。它能把 decode 从纯 memory-bound 往 compute-bound 拉一点,但也引入新的 KV 管理问题:
- 候选路径会产生临时 KV。
- 验证失败后需要 rollback。
- 多分支并发时,KV block 的生命周期更复杂。
- Prefix sharing 和 copy-on-write 会变得更重要。
因此下一代推理引擎不能只支持“线性追加 KV”,还要支持分支、验证、回滚、复用和快速释放。
7.2 安全与对齐可能被压缩悄悄伤害
激进驱逐和极低比特量化可能影响的不只是准确率,还包括安全行为。
原因是:
- 长 prompt 里的安全约束 token 可能被驱逐。
- 对齐行为可能依赖某些层、某些 head 的精细激活。
- 量化误差可能改变拒答、边界判断、工具调用策略。
这类问题很难只靠 perplexity 发现。真正上线前需要额外做:
- NIAH / long-context retrieval 回归。
- 安全红队测试。
- 多轮 Agent 记忆一致性测试。
- 数学、代码、法律等高精度任务分组评估。
7.3 多模态和 Agent 会让 KV 生命周期变长
文本聊天里,请求结束后 KV 就可以释放。但 Agent 和多模态场景会让 KV 生命周期变长:
- Agent 可能跨多轮、跨工具调用保留工作记忆。
- 视频/屏幕流会不断追加视觉 token。
- RAG 文档缓存可能被大量用户复用。
- 同一任务的中间状态可能跨节点迁移。
这意味着 KV Cache 会越来越像服务系统里的“一等缓存对象”,需要命名、索引、过期、迁移、权限控制和成本核算。
八、到底该选哪个方案:工程选型指南
KV Cache 方案没有银弹,只有按瓶颈下药。
8.1 三分钟决策版
| 你的主要症状 | 首选方案 | 进一步升级 | 需要注意什么 |
|---|---|---|---|
| 多并发吞吐低,GPU 利用率差 | PagedAttention + Continuous Batching | Chunked Prefill、Prefix Caching | 先解决碎片和调度,不要急着改模型 |
| 大量请求共享 system prompt / RAG 前缀 | Prefix Caching / RadixAttention | CacheBlend、缓存感知路由 | 命中率决定收益上限 |
| 已有模型 KV 太大 | 优先选 GQA/MLA 架构模型 | KV 量化、Mixed-Precision | 不同模型结构的 KV 分布不同 |
| 新训长上下文模型 | GQA 起步,MLA/NSA/混合注意力优先评估 | CSA/HCA、KDA+MLA、CLA | 架构收益最干净,但训练成本最高 |
| 单请求上下文太长,显存顶不住 | KV 量化 | 驱逐、DMC、ShadowKV | 是否允许有损,是第一判断条件 |
| 无限流式对话 | StreamingLLM | AdaKV、DMC | 不适合远距离精确回忆 |
| 多模态图片/视频 token 爆炸 | 视觉 token merging / saliency pruning | VLM 原生 MLA/稀疏注意力 | 不能简单套文本压缩策略 |
| 必须突破单机显存上限 | CPU DRAM Offloading | CXL Pool、分布式 KV Store、NMP | 能放下不等于跑得快 |
| 跨节点 Prefill/Decode 解耦 | Mooncake / KV Store / Transfer Engine | 统一 KV 传输层、RDMA、缓存路由 | KV layout 和压缩格式要能互通 |
8.2 更实用的判断顺序
如果你在做真实服务,可以按这个顺序排查:
- 先量化瓶颈:到底是算力、HBM 带宽、显存容量、网络传输,还是调度碎片?
- 先做系统层:PagedAttention、Continuous Batching、Prefix Caching 通常是最稳的第一步。
- 再选模型结构:同等质量下,优先选 GQA/MLA/长上下文友好的模型。
- 再上近无损压缩:KV 量化通常比激进驱逐更稳。
- 最后考虑有损驱逐和 Offloading:它们能救容量,但必须接受延迟或质量风险。
- 所有方案都用业务集回归:通用榜单不能证明你的合同、代码、Agent、RAG 场景安全。
8.3 防坑清单
不要把这些结论记反
- PagedAttention 主要解决内存管理和碎片,不会改变 KV Cache 的理论大小。
- Prefix Caching 的收益上限由前缀命中率决定,命中率低时不要神化它。
- GQA/MLA 是模型结构收益,不是推理时随便开关。
- 驱逐类方法是有损压缩,代码、法律、长文档检索要特别谨慎。
- 极低比特 KV 量化在闲聊里看似无损,不代表在数学、代码、NIAH 上无损。
- Offloading 能扩大容量,但很难免费保持低延迟。
- 新架构的 KV 分布可能不同,普通 MHA/GQA 上的量化和裁剪经验不能直接照搬到 MLA、CSA/HCA、KDA+MLA。
九、接下来会往哪走
9.1 KV Cache 会变成训练、推理、系统联合设计
未来不会是一条路线赢,而是几条路线合流:
- 模型结构上先用 GQA / MLA / 混合稀疏注意力减少原始 KV。
- 推理层再用量化、混合精度、查询感知选择降低运行成本。
- 系统层用分页、前缀复用、Prefill/Decode 解耦、分布式 KV Store 把吞吐吃满。
- 硬件层用更大 HBM、CXL、近内存计算继续改变边界。
KV Cache 不再是模型里的中间状态,而会成为一个跨训练、部署、调度、硬件设计的核心对象。
9.2 百万上下文会迫使架构重做
128K 上下文还能靠 GQA、量化、PagedAttention、offloading 拼出来;到了 1M 甚至更长,单纯“把更多 KV 放进更大显存”不再经济。
真正可持续的方案必须包含:
- 原生稀疏或压缩注意力。
- 层级记忆结构。
- Query-aware 检索。
- 多级 KV 存储。
- 可复用的全局前缀缓存。
也就是说,百万上下文不是把 128K 方案线性放大,而是迫使模型和系统一起重构。
9.3 多模态会成为最大压力源
文本的长上下文已经很难,多模态会更难。图片、视频、屏幕流、工具轨迹会把 token 数推到更高量级,而且视觉 token 的冗余结构和文本不同。
未来 VLM 的 KV Cache 优化大概率会走专门路线:
- 视觉 token merging。
- 空间 saliency pruning。
- 跨帧缓存复用。
- 文本 query 引导的视觉 KV 激活。
- 多模态 prefix caching。
这会让 KV Cache 从“LLM 推理优化”变成“通用多模态记忆系统”。
结语
KV Cache 这个话题表面上是推理优化,底层其实是 LLM 系统的成本中枢。
它横跨五个层面:
- 系统工程:分页、调度、前缀复用、Prefill/Decode 解耦。
- 模型架构:GQA、MLA、NSA、CSA/HCA、KDA+MLA。
- 推理算法:驱逐、合并、查询感知选择、动态摘要。
- 数值压缩:KIVI、KVQuant、GEAR、SmoothKV、TurboQuant、Mixed-Precision。
- 存储硬件:CPU/SSD Offloading、CXL、分布式 KV Store、近内存计算。
如果你做的是 LLM 推理服务,KV Cache 不是“实现细节”。它决定了你的上下文长度、并发上限、首 token 延迟、单 token 成本、硬件选型,甚至模型架构选择。
未来的推理系统,谁能把 KV Cache 管成一等资源,谁就更接近长上下文和多模态 Agent 的真实生产形态。
参考文献与延伸阅读
- Kwon et al. 2023, vLLM / PagedAttention
- Yu et al. 2022, Orca / Continuous Batching
- Zheng et al. 2024, SGLang / RadixAttention
- DeepSeek-AI 2024, DeepSeek-V2 / MLA
- DeepSeek-AI 2026, DeepSeek-V4 / CSA, HCA, mHC
- Moonshot AI 2025, Kimi Linear / KDA + MLA
- Zhang et al. 2023, StreamingLLM
- Zhang et al. 2023, / Heavy-Hitter Oracle
- Cai et al. 2024, PyramidKV
- Liu et al. 2024, KIVI
- Hooper et al. 2024, KVQuant
- Kang et al. 2024, GEAR
- Zandieh et al. 2025, TurboQuant
- ByteDance 2025, ShadowKV
- Mooncake 2025, KVCache-centric Disaggregated Architecture for LLM Serving
- NVIDIA TensorRT-LLM Docs, KV Cache System