4. KV Cache原理与优化
各位同学,今天我们来聊聊大模型推理里一个绕不开的话题——KV Cache。说实话,我第一次接触这个概念时,也觉得不就是缓存一下中间结果嘛,有什么好讲的?直到我在实际项目中,被显存爆炸的问题折磨得死去活来,才真正意识到这东西有多关键。
4.1 KV Cache是什么?
先问个问题:大模型做推理时,是怎么生成一个词的?
以GPT这样的自回归模型为例,生成第N个词时,需要把前面N-1个词全部重新过一遍Transformer。你想想看,这得多浪费?每次生成新词,前面算过的Key和Value都得重算一遍。
KV Cache就是干这个的——把之前计算好的Key矩阵和Value矩阵存下来。下次生成新词时,只需要算新词的Query,然后跟缓存的Key、Value做注意力计算就行。
核心定义:KV Cache是Transformer解码过程中,对历史token的Key和Value矩阵进行缓存的技术。它避免了重复计算,是自回归生成加速的关键手段。
我习惯用一个比喻来理解:你写文章时,前面写过的段落不需要重写一遍,只需要接着往下写就行。KV Cache就是帮你记住前面写了什么。
4.2 为什么需要KV Cache?
没有KV Cache会怎样?我们来算笔账。
假设模型有L层,每层注意力头数为H,每个头的维度为d。生成序列长度为S。没有KV Cache时,生成第S个token需要计算前面S-1个token的完整注意力。复杂度是O(S²)。
有了KV Cache呢?每次只需要计算新token的注意力,复杂度降到O(S)。
| 场景 | 计算复杂度 | 实际感受 |
|---|---|---|
| 无KV Cache | O(S²) | 生成100个词,要算10000次注意力 |
| 有KV Cache | O(S) | 生成100个词,只算100次 |
我在项目中遇到过,一个7B模型,生成512个token时,没有KV Cache的推理速度慢了将近10倍。说白了,没有KV Cache,长文本生成基本没法用。
4.3 显存占用分析
好了,KV Cache这么好,那它有没有代价?当然有——显存。
我们来算一下KV Cache的显存占用公式:
KV Cache显存 = 2 × L × H × d × S × 精度字节数
其中:
- L:层数
- H:注意力头数
- d:每个头的维度
- S:序列长度
- 2:Key和Value各一份
举个例子,LLaMA-13B模型:
- L = 40层
- H = 40头
- d = 128维
- 精度 = FP16(2字节)
生成2048个token时:
KV Cache = 2 × 40 × 40 × 128 × 2048 × 2 = 1.6 GB
注意:这只是一个请求的KV Cache!如果并发处理多个请求,显存会线性增长。我曾经在部署服务时,就因为没算清楚这笔账,导致8张A100的显存被吃满,服务直接OOM。
更可怕的是,KV Cache的显存占用跟序列长度成正比。处理长文档时,比如10万token的上下文,KV Cache能吃掉几十GB显存。
4.4 PageAttention与vLLM的实现
显存问题怎么解决?vLLM给出了一个漂亮的方案——PageAttention。
这个名字是不是很眼熟?对,它借鉴了操作系统的虚拟内存分页思想。
传统做法是:为每个请求预分配一块连续的显存,存放KV Cache。但问题是,你没法提前知道请求最终会生成多长的序列。预分配少了,生成到一半显存不够;预分配多了,造成浪费。
PageAttention的思路是:把KV Cache切成固定大小的块(Page),每个块可以独立分配和释放。就像操作系统管理内存页一样。
vLLM的具体实现有几个关键点:
- 块大小设计:每个Page通常包含16或32个token的KV值。太小了管理开销大,太大了浪费。
- 物理块池:预先分配一大块显存,切成等大小的物理块。请求来了,按需分配物理块。
- 逻辑页表:每个请求维护一个逻辑到物理的映射表。生成新token时,如果当前页满了,就申请新页。
- Copy-on-Write:多个请求共享相同前缀时,物理块可以共享。只有需要修改时才复制。
我的经验:在实际部署中,PageAttention能把显存利用率从60%提升到95%以上。特别是处理长序列时,效果非常明显。我曾经用vLLM部署一个70B模型,8张A100可以同时处理32个并发请求,每个请求生成2048个token,这在传统方案下根本不可能。
不过要注意,PageAttention也不是银弹。它增加了内存管理的复杂度,CPU和GPU之间的页表同步也有开销。但对于长文本生成场景,这点开销完全值得。
嗯,KV Cache这块内容就讲到这里。从原理到显存分析,再到PageAttention的实现,希望能帮你建立起一个完整的认知。下次遇到显存瓶颈时,记得想想今天讲的这些优化手段。
核心要点回顾:
- KV Cache避免重复计算,是自回归推理加速的关键
- 显存占用随序列长度线性增长,长文本场景下是主要瓶颈
- PageAttention通过分页管理,解决了显存碎片和浪费问题
- vLLM的Copy-on-Write机制进一步提升了内存共享效率