大模型进入长上下文和高并发推理后,显存瓶颈往往不只来自模型权重,还来自持续增长的 KV Cache。压缩 KV Cache 看似只是“少存一些数据”,实际却会改变模型能够回看的历史信息,因此真正的问题不是压得多小,而是在给定显存预算下,保留哪些信息、采用多低的精度,以及如何控制生成质量的退化。
KV Cache 为什么会成为显存瓶颈
自回归生成每个新 token 时,模型都要使用先前 token 的 Key 和 Value。缓存这些张量可以避免重复计算,但其占用会随批量大小、上下文长度、网络层数和 KV 头维度增长。粗略地说,KV Cache 显存可表示为:批量大小 × token 数 × 层数 × KV 头数 × 单头维度 × Key/Value 两份数据 × 每元素字节数。
这意味着同一个模型在短提示、低并发场景下可能运行顺畅,一旦切换到长文档问答、多轮对话或大批量服务,KV Cache 就可能挤占可用于批处理的显存。与此同时,解码阶段需要反复读取缓存,压缩如果能减少访存量,也可能改善吞吐,而不只是让模型“装得下”。
三类主流压缩方法
一、量化:减少每个缓存元素的字节数
量化保留 token 数量,但将 FP16 或 BF16 的 KV 张量转换为更低位宽。其优点是历史位置仍然存在,比较适合检索、代码补全和复杂指令等不能轻易丢失早期信息的任务。难点在于 Key 与 Value 的数值分布不同,若使用完全相同的量化粒度,异常值可能放大量化误差。KIVI 因此采用非对称设计,对 Key 按通道、Value 按 token 处理,说明 KV 量化不宜简单套用权重量化方案,参见 KIVI 论文。
二、稀疏化与淘汰:减少保留的 token 数
这类方法为缓存设置固定预算,只保存最近 token、注意力高分 token 或特定锚点。H2O 会动态保留近期内容与“重度贡献”token,其核心假设是少量位置贡献了大部分注意力价值,参见 H2O 论文。SnapKV 则从提示末尾的观察窗口推断各注意力头关注的位置,再聚类选择重要 KV,参见 SnapKV 论文。
淘汰法通常具有更高的压缩上限,但风险也更直接:被删除的信息无法通过后续计算恢复。摘要任务可能容忍部分细节损失,而“在长文档中找一个编号”、跨段推理、系统指令遵循或多轮对话中的早期约束,往往对错误淘汰更敏感。
三、混合压缩:同时控制位宽与 token 预算
工程上更稳妥的方案通常不是二选一,而是分层处理:近期窗口和关键锚点使用较高精度,较老但仍重要的缓存采用低比特量化,低价值位置再执行淘汰。这样可以把量化误差与信息丢失分散到不同区域,避免一次激进操作造成明显质量坍塌。
如何找到质量与显存的平衡点
- 先定义质量底线:不要只测困惑度,应按业务加入长文档检索、事实一致性、格式遵循、多轮记忆、代码正确率和长解码推理等指标。
- 用真实长度分布测试:分别覆盖常见输入、长尾输入和最大上下文。只在短样本上验证,无法暴露早期信息被淘汰的问题。
- 逐级压缩:从较保守的位宽和缓存预算开始,记录质量、峰值显存、首 token 延迟、单 token 延迟及吞吐,再逐步收紧预算,寻找质量曲线出现明显拐点的位置。
- 保护敏感区域:系统提示、最近窗口、文档标题、用户约束和结构标记可设置为不可淘汰或高精度区域,降低指令遗忘和上下文漂移。
- 按请求动态调整:闲聊、摘要可使用更高压缩率;数学推理、代码生成和精确检索应保留更大预算。统一配置虽然简单,却通常不能兼顾成本与稳定性。
压缩率只是中间指标。真正需要优化的是单位显存能够承载的有效请求数,以及在目标质量阈值下获得的端到端吞吐。
落地时容易忽略的问题
算法上的显存节省不一定自动转化为速度提升。量化需要反量化内核,动态淘汰需要维护分数与索引,非连续 KV 布局还可能降低内存访问效率。因此部署前必须确认推理框架、分页缓存、注意力内核和硬件是否真正支持目标格式。若压缩产生大量数据搬运或内核切换,最终可能只降低显存,却没有改善延迟。
总结
KV Cache 压缩的关键不是追求单一的最高压缩倍数,而是根据任务的信息敏感度选择手段:量化适合尽量保留完整历史,淘汰适合上下文冗余较高且预算严格的场景,混合方案则更适合生产系统。以真实业务集建立质量底线,保护关键 token,并结合显存、延迟和吞吐联合评估,才能把压缩从论文指标转化为稳定可用的推理能力。