30 秒快速回答
KV Cache(键值缓存)是大模型推理时,把已计算过的注意力 Key 和 Value 矩阵暂存在显存里、避免重复计算的加速技术。 它是所有主流推理引擎(vLLM、SGLang、TensorRT-LLM)和云端 API 加速的基石——没有它,每生成一个新 token 都要把前面整段对话重新算一遍,成本暴涨数十倍。同时它也是推理时显存占用的「头号大户」,直接决定了服务能开多大并发。
核心价值一句话:看懂 KV Cache,你就看懂了大模型推理的提速与降本逻辑。
一、为什么需要 KV Cache?——重复计算的浪费
先看大模型是怎么「写」字的。LLM 采用自回归解码:一次只生成一个 token,然后把新 token 拼回输入继续生成。假设输入 100 个 token、要生成 200 个 token:
- 生成第 101 个 token 时,需要计算前 100 个 token 的注意力
- 生成第 102 个 token 时,又需要重新计算前 101 个 token 的注意力
- ……
如果不做任何缓存,总计算量是 100+101+102+…+300,其中绝大部分是重复劳动——第 1 个 token 的注意力被白算了 200 次。
KV Cache 的做法:每个 token 的 K、V 矩阵算过一次后就存进显存,后续新 token 只需与缓存里的 K、V 做注意力计算,不再重算历史前缀。
| 方式 | 生成 200 token 的计算量 | 相对开销 |
|---|---|---|
| 无 KV Cache | 反复重算全部前缀 | 高 10-100 倍 |
| 有 KV Cache | 只算新 token 的增量 | 1x(基准) |
二、KV Cache 到底存了什么?
Transformer 的每一层自注意力,都会为每个 token 计算三组向量:Query(Q)、Key(K)、Value(V)。其中 Q 只服务于当前 token 的查询,用完即弃;而 K、V 需要被之后所有 token 复用,因此被缓存下来。
简单说,缓存的就是:每一层、每个 token、每个注意力头的 K 和 V 张量。
# 伪代码:带缓存的自注意力(单层)
def attention_with_cache(q, k, v, cache):
# cache 里存着之前所有 token 的 K、V
k = torch.cat([cache.k, k], dim=1) # 拼上新 token 的 K
v = torch.cat([cache.v, v], dim=1) # 拼上新 token 的 V
scores = q @ k.transpose(-2, -1) / math.sqrt(d_k)
attn = torch.softmax(scores, dim=-1)
return attn @ v, (k, v) # 返回更新后的缓存
关键洞察:KV Cache 不改变任何计算结果,只是用显存换时间——典型的空间换时间策略,这也是它能在不损失质量的前提下加速的原因。
三、KV Cache 有多吃显存?——一个公式算清楚
KV Cache 的大小由四个因素决定:
KV Cache 大小 = 2 × 层数 × 头数 × 头维度 × 序列长度 × 精度字节
以 Llama-2-70B(80 层、64 头、头维度 128、FP16)生成 4096 token 为例:
2 × 80 × 64 × 128 × 4096 × 2 字节 ≈ 10.7 GB
对比:模型权重本身约 140GB(FP16),KV Cache 可占权重的 7%-10%,且随序列长度线性增长。这也是为什么 128K 长上下文部署成本急剧上升——KV Cache 成了真正的显存瓶颈。
| 模型 | 上下文 4K 的 KV Cache | 上下文 128K 的 KV Cache |
|---|---|---|
| 7B(32层、32头) | ~1.3 GB | ~42 GB |
| 70B(80层、64头) | ~10.7 GB | ~340 GB |
四、主流优化技术:怎么给 KV Cache 瘦身?
4.1 GQA / MQA / MLA:共享 KV 头
标准多头注意力(MHA)每个头都有独立的 K、V。GQA(分组查询注意力)让多个 Q 头共享一组 K、V 头,MQA 则让所有 Q 头共享同一组 K、V,参数量几乎不变,KV Cache 却显著缩小:
| 技术 | KV 头数 | KV Cache 相对大小 | 代表模型 |
|---|---|---|---|
| MHA | 64 | 1x(基准) | GPT-3 |
| GQA | 8 | ~1/8 | Llama 2/3、Qwen |
| MQA | 1 | ~1/64 | Falcon、PaLM |
| MLA | 低秩压缩 | ~1/12 且不降质量 | DeepSeek-V2/V3 |
MLA(多头潜在注意力)是 DeepSeek 的招牌创新:把 K、V 压缩成低秩潜向量,缓存的是压缩结果,显存占用大幅下降——这也是 DeepSeek 能维持超低推理成本的关键之一。
4.2 KV Cache 量化:从 FP16 到 FP8/INT8
KV Cache 本身也能量化,把缓存张量从 FP16 压到 FP8/INT8,显存直接减半,精度损失通常很小。vLLM 一行命令开启:
vllm serve Qwen/Qwen2.5-7B-Instruct --kv-cache-dtype fp8
4.3 滑动窗口注意力(SWA)
只缓存最近 N 个 token 的 KV,丢弃更早的。显存占用从「随序列线性增长」变为「封顶」,非常适合流式对话与长文档场景,Mistral 系列即采用此方案。
4.4 PagedAttention 与 KV 复用
- PagedAttention(vLLM 核心):把 KV Cache 切成固定大小块,按需分配、零碎片、支持跨请求共享,单卡吞吐可提升数十倍
- 前缀缓存 / Prompt Caching:多轮对话或大量请求共享相同前缀时,直接复用已算好的 KV,首 token 延迟大幅下降
五、代码示例:一键开关看差距
用 HuggingFace Transformers 可以直观感受 KV Cache 的影响:
from transformers import AutoModelForCausalLM, AutoTokenizer
model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2.5-7B-Instruct")
tok = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-7B-Instruct")
inputs = tok("请写一段关于人工智能的简介:", return_tensors="pt")
# 关闭 KV Cache:每个新 token 都重算整段前缀
out_off = model.generate(**inputs, max_new_tokens=512, use_cache=False)
# 开启 KV Cache(默认):增量计算,速度快数倍
out_on = model.generate(**inputs, max_new_tokens=512, use_cache=True)
在 7B 模型、输出 512 token 的场景下,开启 KV Cache 通常快 5-10 倍以上。生产环境(vLLM/SGLang)则进一步叠加 PagedAttention、GQA、KV 量化等手段,把推理成本压到极致。
总结
KV Cache 是大模型推理最核心的「空间换时间」机制:
- 作用:缓存 K、V 矩阵,避免自回归解码重复计算,加速数倍
- 代价:显存随层数 × 头数 × 序列长度线性增长,是并发瓶颈
- 优化:GQA/MQA/MLA 减少 KV 头、KV 量化降精度、滑动窗口限制长度、PagedAttention 消除碎片
- 趋势:2026 年推理成本持续下降,MLA、FP8 量化、前缀复用等 KV Cache 优化正是最大功臣
延伸阅读: