为什么要理解 Prefill 和 Decode
当你向 ChatGPT 发送一条消息,背后的推理过程并不是一个单一的”计算”——它分成两个截然不同的阶段,具有完全不同的计算特性和性能瓶颈。
理解这两个阶段,以及连接它们的 KV Cache 机制,是优化 LLM 部署、降低延迟、提升吞吐量的基础。
第一阶段:Prefill(预填充)
发生了什么
用户提交输入后,Prefill 阶段开始:
- 输入文本被分词(Tokenization),转换为 Token ID 序列
- Token 被嵌入为数值向量
- 向量通过多个 Transformer 层,为每个 Token 计算 Query(Q)、Key(K)、Value(V) 向量
- 模型将每一层、每个 Token 的 K 和 V 向量存入 KV Cache
关键特性
- 高度并行:整个提示词序列在同一时刻完全可用,所有 Token 可以并行处理,是典型的矩阵 - 矩阵运算,GPU 利用率充分
- 计算密集型(Compute-bound):瓶颈在 GPU 算力,而非内存带宽
- 监控指标:TTFT(Time To First Token)——从提交提示词到生成第一个 Token 的延迟
第二阶段:Decode(解码)
发生了什么
Prefill 完成后进入 Decode 阶段,模型逐个自回归地生成 Token:
- 基于当前上下文的概率分布,采样出下一个 Token
- 新 Token 的 K/V 被追加到 KV Cache
- 重复,直到达到最大长度、遇到停止词或序列结束标记(EOS)
关键特性
- 顺序执行(Sequential):每个 Token 依赖前一个,无法并行,是矩阵 - 向量运算
- 内存密集型(Memory-bound):瓶颈不是算力,而是从 GPU 显存读取 KV Cache 的带宽
- GPU 利用率偏低:相比 Prefill,Decode 阶段 GPU 算力普遍处于欠饱和状态
- 监控指标:ITL(Inter-Token Latency)——相邻 Token 生成之间的时间间隔
两个阶段的冲突
Prefill 和 Decode 无法完全并行运行:计算密集的 Prefill 占用 GPU 时,会直接增加 Decode 的 Token 延迟,反之亦然。这是 LLM 服务系统设计的核心挑战之一,也是”Prefill-Decode 分离部署”方案兴起的背景。
KV Cache:消除重复计算的关键
没有 KV Cache 会怎样
在 Decode 阶段,生成第 N 个 Token 时,注意力机制需要”看到”前 N-1 个 Token 的信息。如果不缓存,每生成一个新 Token 都要对所有历史 Token 重新跑一遍前向传播——计算量随序列长度线性增长,代价极高。
KV Cache 的原理
KV Cache 利用了一个关键事实:一旦某个 Token 的 Key 和 Value 被计算出来,在后续步骤中它们不会改变。
- Prefill 阶段:计算所有输入 Token 的 K/V,存入缓存
- Decode 阶段:每一步只计算新 Token 的 K/V,追加到缓存;历史 Token 的 K/V 直接从缓存读取
这样,每步推理的计算量恒定,不随序列长度增长。
KV Cache 的内存开销
KV Cache 虽然省算力,但消耗显存。单 Token 的 KV Cache 大小(字节):
2 × 层数 × (注意力头数 × 头维度) × 精度字节数完整 KV Cache 大小(字节):
批大小 × 序列长度 × 2 × 层数 × 隐藏层大小 × sizeof(FP16)实际案例:Llama 2 7B,FP16 精度,批大小为 1 时,KV Cache 约占 2 GB 显存。随着批大小和序列长度增加,显存需求线性扩张,这正是制约吞吐量的核心瓶颈。
注意力变体对 KV Cache 的影响
不同注意力机制在 KV Cache 大小上差异显著:
机制 | K/V 头数 | KV Cache 大小 | 特点 |
多头注意力(MHA) | 与 Q 头数相同 | 最大 | 表达能力最强 |
多查询注意力(MQA) | 1 | 最小 | 需专门训练,性能有损 |
分组查询注意力(GQA) | 介于两者之间 | 居中 | 性能与效率的平衡点(Llama 3、Qwen3 采用) |
Token 采样策略
Decode 阶段,模型输出的是一个概率分布,通过采样策略选出下一个 Token:
策略 | 说明 |
贪心解码(Greedy) | 每步选概率最高的 Token,确定性强但多样性差 |
Top-k 采样 | 从概率最高的 k 个 Token 中随机采样 |
Top-p(核)采样 | 从累计概率 ≥ p 的最小 Token 集中采样 |
温度(Temperature) | 调整分布形状:低温→更确定,高温→更多样 |
推理慢的根本原因
- 顺序解码:Token 逐个生成,天然限制并行度
- 显存带宽瓶颈:Decode 阶段反复从显存读取 KV Cache,受制于内存带宽而非算力
- 模型体积:参数越多,每步加载的权重越大
- 序列长度:上下文越长,KV Cache 越大,读取开销越高
优化方向速览
优化技术 | 解决的问题 |
PagedAttention(vLLM) | KV Cache 内存碎片化,提升显存利用率 |
FlashAttention | 减少注意力计算的 GPU 内存读写次数 |
Prefill-Decode 分离部署 | 两阶段计算特性不同,分开调度更高效 |
投机推理(Speculative Decoding) | 用小模型草稿 + 大模型验证,提升 Decode 吞吐 |
量化(INT8/FP8) | 压缩 KV Cache 大小和权重体积 |
GQA / MQA | 在模型层面减小 KV Cache 尺寸 |
小结
LLM 推理的核心结构可以用一句话概括:
并行的 Prefill 填满 KV Cache,顺序的 Decode 逐步消费它。
- Prefill 是计算密集的并行阶段,决定首 Token 延迟(TTFT)
- Decode 是内存密集的串行阶段,决定生成速度(ITL)
- KV Cache 是两者之间的桥梁——用显存空间换计算重复
无论是做模型部署调优、服务架构设计,还是理解 vLLM / SGLang 这类推理框架的设计决策,都绕不开这三个概念。
参考资料