推理架构基础:Transformer Decoder架构、自回归生成机制、KV Cache原理
聊大模型推理,绕不开这三个东西:Decoder架构、自回归生成、KV Cache。我刚开始接触推理优化时,觉得这些概念太理论了,直到亲手调过几个模型,才发现——不懂这些,你连性能瓶颈在哪都找不到。
1. Transformer Decoder架构:推理的“心脏”
大模型推理用的基本都是Decoder-only架构。说白了,就是只有解码器,没有编码器。GPT系列就是典型代表。
一个Decoder层长什么样?我画了张图,你一看就明白:
每个Decoder层就干三件事:
- Masked Multi-Head Self-Attention:带因果掩码的自注意力。只能看当前位置及之前的位置,不能偷看未来的token。这是自回归生成的关键约束。
- Add & LayerNorm:残差连接加层归一化。残差连接解决梯度消失,LayerNorm稳定训练。
- Feed-Forward Network:两层全连接,中间通常放大4倍。比如GPT-3的隐藏层12288,FFN中间层就是49152。
- 输入“[BOS]”,预测“我”
- 输入“[BOS] 我”,预测“爱”
- 输入“[BOS] 我爱”,预测“北”
- 输入“[BOS] 我爱北”,预测“京”
- ……直到预测出“[EOS]”
- Prefill阶段(也叫预填充阶段):处理输入的prompt,一次性计算所有token的K和V,存入缓存。这个阶段是并行的,速度快。
- Decode阶段(也叫生成阶段):每次只生成一个token。从缓存中读取之前所有token的K和V,只计算当前token的Q,然后做注意力计算。生成完新token后,把它的K和V也加入缓存。
2. 自回归生成机制:一个词一个词往外蹦
自回归生成,说白了就是“用已经生成的词,预测下一个词”。每次只生成一个token,然后把新token拼到输入里,继续预测下一个。
举个例子,生成“我爱北京天安门”:
这个过程有什么问题?你想想看——每次都要重新计算前面所有token的注意力。假设生成了100个token,第100步就要计算100次注意力。复杂度是O(n²),n是序列长度。
那怎么办?KV Cache就是来解决这个问题的。
3. KV Cache原理:用空间换时间
KV Cache的核心思想很简单:把之前计算过的Key和Value缓存起来,避免重复计算。
我画个图对比一下,你就懂了:
具体怎么做的?我拆解一下:
KV Cache的大小怎么算?公式很简单:
KV Cache大小 = 2 × 层数 × 隐藏层维度 × 序列长度 × 精度字节数
举例:GPT-3 175B
- 层数:96
- 隐藏层维度:12288
- 序列长度:2048
- 精度:FP16(2字节)
KV Cache = 2 × 96 × 12288 × 2048 × 2 = 9.66 GB
关键数据:一个175B模型,单条请求的KV Cache就要近10GB显存。如果并发100条请求,光KV Cache就要1TB显存。这就是为什么大模型推理这么吃显存。
4. 实际推理中的性能瓶颈
了解了这些基础,我们来看看实际推理中哪里最慢:
| 阶段 | 计算特点 | 瓶颈 | 占比(典型值) |
|---|---|---|---|
| Prefill | 并行计算,计算密集型 | 矩阵乘法(GEMM) | 20-30% |
| Decode | 串行计算,访存密集型 | KV Cache读写 + Attention | 70-80% |
Prefill阶段虽然计算量大,但因为可以并行,GPU利用率高。Decode阶段才是真正的瓶颈——每次只算一个token,GPU利用率可能不到10%。
5. 避坑指南
最后分享几个我踩过的坑:
- KV Cache内存管理:我曾经没做内存预分配,每次生成新token都动态申请显存,结果频繁的cudaMalloc把推理速度拖慢了5倍。一定要预分配最大序列长度的缓存空间。
- Batch推理时的KV Cache:不同请求的序列长度不一样,KV Cache大小也不同。我见过有人用padding对齐,结果浪费了大量显存。更好的做法是用动态batch,按实际长度分配。
- 精度选择:FP16的KV Cache比FP32省一半显存,但精度损失可以忽略。我建议默认用FP16,显存紧张时可以用INT8量化。
嗯,以上就是Transformer Decoder架构、自回归生成和KV Cache的核心内容。这些是推理优化的地基,后面讲的各种加速技术——比如FlashAttention、PageAttention、量化推理——都是在这个基础上做的优化。
公众号:蓝海资料掘金营,微信deep3321