KV Cache 是大模型自回归推理中最核心的优化之一。
它的核心思想是:在自回归生成时,缓存已经计算过的 Key 和 Value,避免每一步都重新计算历史 token 的 K、V。
没有 KV Cache,生成第 $t$ 个 token 时要把前面 $t-1$ 个 token 全部重新算一遍,计算量随序列长度平方增长。有了 KV Cache,每一步只需要计算当前 token 的 Q、K、V,然后和缓存的 K、V 做注意力。
一句话总结:KV Cache 用显存换计算,把推理从平方复杂度降到近似线性复杂度。
但它也带来新的问题:显存占用随序列长度和 batch size 线性增长,成为长上下文、大并发场景下的主要瓶颈。
大模型生成是逐 token 进行的:
在 Self-Attention 中,每个 token 都要计算 Query、Key、Value:
$$ Q = XW_Q,\quad K = XW_K,\quad V = XW_V $$
注意力计算为:
$$ \text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V $$
如果没有 KV Cache,生成第 $t$ 个 token 时:
这样每生成一个 token,都要重算历史,计算量随序列长度快速增长。
有了 KV Cache:
这样历史 token 的 K、V 只算一次,后续直接复用。
没有 KV Cache 时,生成 $n$ 个 token 的总计算量约为:
$$ O(n^2) $$
有了 KV Cache 后,总计算量约为:
$$ O(n) $$
这就是 KV Cache 最核心的价值。
KV Cache 的显存占用可以用下面的公式估算:
$$ \text{KV Cache Size} = 2 \times L \times b \times s \times h \times d \times \text{bytes} $$
其中:
也可以写成:
$$ \text{KV Cache Size} = 2 \times L \times b \times s \times d_{\text{model}} \times \text{bytes} $$
其中 $d_{\text{model}} = h \times d$ 是隐藏维度。
假设:
则 KV Cache 大小约为:
$$ 2 \times 80 \times 16 \times 4096 \times 8192 \times 2 \approx 1.37 \times 10^{11} \text{ bytes} $$
也就是约 137 GB。
这还只是 KV Cache,不包括模型权重本身。可见长上下文、大 batch 下 KV Cache 有多可怕。
KV Cache 成为显存瓶颈,主要有几个原因:
第一,随序列长度线性增长。 序列越长,缓存越大。长上下文场景下,KV Cache 可能超过模型权重。
第二,随 batch size 线性增长。 并发请求越多,每个请求都要一份 KV Cache,显存迅速吃紧。
第三,随层数和隐藏维度线性增长。 模型越大,KV Cache 越大。
第四,显存碎片化。 传统实现中,每个请求的 KV Cache 需要预分配连续显存,长度不一导致碎片严重,利用率低。
自回归解码每一步都要读取整个 KV Cache,计算注意力。
这一步是显存带宽受限的:
序列越长、batch 越大,读取 KV Cache 的时间越长,吞吐越低。
KV Cache 占用大量显存,导致:
这就是为什么长上下文推理时,吞吐会明显下降。
推理分两个阶段:
KV Cache 主要在 Decode 阶段成为瓶颈。
把 KV Cache 从 FP16 量化到 INT8 或 INT4:
显存直接减半甚至更多,但可能带来精度损失。
让所有注意力头共享同一组 K、V:
KV Cache 减少到原来的 $1/h$。
折中方案:
KV Cache 减少到原来的 $1/g$,$g$ 是分组数。
LLaMA 2、LLaMA 3 等模型都采用 GQA。
DeepSeek 提出的方法:
能大幅压缩 KV Cache,同时保持较好效果。
vLLM 的核心技术:
如果多个请求有相同的前缀,比如相同的 system prompt:
请求结束后及时回收 KV Cache,提高显存复用率。
通过分块计算和重排,减少显存读写:
不同请求的生成进度不同:
用一个小模型快速生成多个候选 token,再用大模型验证:
只保留最近 $w$ 个 token 的 KV:
Mistral 等模型采用这种方式。
只计算部分注意力连接,减少 KV 需求。
用固定大小的状态代替 KV Cache,从根本上避免缓存增长。
比如 Mamba 等架构。
| 优化手段 | 优化目标 | 核心思想 | 代表工作 |
|---|---|---|---|
| KV 量化 | 减少显存 | 降低数值精度 | INT8/INT4 KV |
| MQA/GQA | 减少显存 | 共享 K、V | LLaMA、PaLM |
| MLA | 减少显存 | 低维潜空间压缩 | DeepSeek |
| PagedAttention | 显存管理 | 分页管理 | vLLM |
| Prefix Caching | 减少重复计算 | 共享前缀 | vLLM、SGLang |
| FlashAttention | 减少读写 | 分块计算 | FlashAttention |
| 连续批处理 | 提升吞吐 | 动态调度 | vLLM、TensorRT-LLM |
| 投机解码 | 提升速度 | 小模型草稿 | Speculative Decoding |
| 滑窗注意力 | 控制缓存 | 只留最近窗口 | Mistral |
| 线性注意力 | 消除缓存 | 固定状态 | Mamba |
这是一道很好的大模型推理优化面试题,适合考察候选人对 KV Cache 和推理性能瓶颈的理解。它既能考察基础原理,也能延伸到工程优化和架构设计。如果候选人能把 KV Cache 的作用、显存计算公式、吞吐瓶颈来源以及常见优化手段都讲清楚,基本可以判断其具备大模型推理优化的扎实基础。
评论专区
评论加载中...登录后即可发表评论