Prefill vs Decode 阶段
更新于 2026-04-23
简介:LLM 推理不是一步完成的
当你向 ChatGPT 提问时,你会注意到两个明显不同的阶段:
- 等待片刻 — 模型在处理你的完整输入(prompt)
- 逐字输出 — 模型开始一个接一个地生成 token
这两个阶段对应着 LLM 推理中的两个根本不同的计算过程:Prefill(预填充) 和 Decode(解码)。它们不仅在功能上不同,在计算特性上也截然相反 — 一个是 compute-bound(计算密集),另一个是 memory-bound(内存带宽密集)。
理解这两个阶段的区别,是理解 LLM 服务性能优化的基础。
Prefill 阶段:并行处理 Prompt
Prefill 阶段的任务是处理用户输入的完整 prompt,为生成阶段做准备。
工作流程
假设 prompt 有 个 token,Prefill 阶段会:
- 将所有 个 token 同时送入模型
- 对每一层 Transformer,计算所有 token 的 Query、Key、Value
- 执行完整的 Self-Attention:每个 token 关注所有之前的 token
- 生成并缓存 KV Cache — 后续 Decode 阶段将复用这些缓存
- 输出第一个生成 token
计算特性
Prefill 的核心计算是大规模矩阵乘法。以一层 Transformer 的 QKV 投影为例:
其中 的形状为 ,每个权重矩阵 的形状均为 。以单个投影(如 )为例,这是一个经典的矩阵-矩阵乘法(GEMM),计算量为:
需要加载的数据量(权重矩阵)约为:
因此 Arithmetic Intensity(算术强度,即每加载一字节数据执行的浮点运算次数)为:
以 FP16 为例(2 bytes),当 prompt 长度 时:
这个值非常高!远超现代 GPU 的计算-带宽比(如 A100 的约 312 FLOPs/Byte),意味着 Prefill 是 compute-bound — GPU 的算力是瓶颈,而非内存带宽。
Prefill 做矩阵×矩阵 (GEMM),Decode 做向量×矩阵 (GEMV)。关键差异在于数据复用率。
权重的每列被 4 行复用 → 数据复用率高
权重的每列只被 1 行用一次 → 加载即丢弃
关键特征
- 所有 token 并行处理:充分利用 GPU 并行能力
- 大矩阵运算: 的 GEMM 操作,GPU 擅长处理
- 高算术强度:计算量远大于数据搬运量
- GPU 利用率高:通常可以达到较高的 MFU(Model FLOPs Utilization)
Decode 阶段:自回归逐 Token 生成
Prefill 完成后,模型进入 Decode 阶段,开始逐个生成新 token。
工作流程
每个 Decode 步骤:
- 取上一步生成的 单个 token 作为输入
- 计算该 token 的 Query、Key、Value
- 将新的 K、V 追加到 KV Cache 中
- 用新 token 的 Query 与完整 KV Cache 做 Attention
- 通过 FFN 层,输出下一个 token 的概率分布
- 采样得到下一个 token,重复以上过程
计算特性
Decode 的核心计算退化为向量-矩阵乘法(GEMV)。以 QKV 投影为例:
其中 的形状为 , 的形状为 。计算量为:
需要加载的数据量不变 — 仍然要加载整个权重矩阵 :
Arithmetic Intensity:
以 FP16 为例:
仅为 1 FLOPs/Byte!远低于 GPU 的计算-带宽比,意味着 Decode 是 memory-bound — 内存带宽是瓶颈,GPU 大量算力被闲置,等待数据加载。
Attention 部分同样是 memory-bound
Decode 时的 Attention 计算也面临同样的问题。新 token 的 query 向量 需要与 KV Cache 中所有 个 key 做点积:
而需要从显存加载的 KV Cache 大小为:
Arithmetic Intensity:
极低的算术强度。随着序列长度 增长,KV Cache 线性增大,加载开销也线性增加。
关键特征
- 每步仅处理 1 个 token:无法利用 GPU 大规模并行能力
- 向量-矩阵运算: 的 GEMV 操作
- 低算术强度:数据搬运量与计算量同阶
- GPU 利用率极低:大部分时间在等待内存读取
对比图:两阶段的计算流程
上图清晰展示了两个阶段的核心区别:
- Prefill 将所有 prompt token 并行送入模型,执行大规模矩阵乘法,是 compute-bound 操作
- Decode 每步仅处理一个 token,执行向量-矩阵乘法并读取完整 KV Cache,是 memory-bound 操作
Compute-bound vs Memory-bound:Arithmetic Intensity 分析
Roofline 模型
要理解为什么 Prefill 和 Decode 的瓶颈不同,需要借助 Roofline 模型。Roofline 模型描述了硬件的两个关键参数之间的关系:
- 峰值算力 (FLOPs/s):GPU 每秒可执行的最大浮点运算次数
- 峰值带宽 (Bytes/s):GPU 显存每秒可传输的最大数据量
两者的比值定义了计算-带宽平衡点:
对于 NVIDIA A100(SXM,FP16 Tensor Core):
判断规则:
- 如果操作的 Arithmetic Intensity ,则该操作是 compute-bound
- 如果 ,则该操作是 memory-bound
两阶段的 Arithmetic Intensity 对比
| 指标 | Prefill ( tokens) | Decode (1 token) |
|---|---|---|
| 线性层 FLOPs | ||
| 线性层 Bytes | ||
| AI (线性层, FP16) | ||
| Attention FLOPs | ||
| Attention Bytes | ||
| AI (Attention, FP16) | 较高 | |
| 瓶颈类型 | Compute-bound | Memory-bound |
以 A100 为例(),prompt 长度 :
- Prefill:AI ,compute-bound。GPU 算力被充分利用
- Decode:AI ,memory-bound。GPU 只利用了约 的峰值算力
这就是为什么 Decode 效率如此之低 — GPU 的绝大部分算力都在空转,等待数据从显存搬运过来。
Batch Size 的影响
增加 batch size 可以提升 Decode 的算术强度。当同时为 个请求做 Decode 时:
权重矩阵只需加载一次,但为 个请求分别计算,计算量乘以 。当 (A100 上 )时,Decode 也能变成 compute-bound。
但实际中有两个限制:
- KV Cache 显存:每个请求的 KV Cache 会占用大量显存,限制了可用的 batch size
- 延迟约束:batch 太大会增加单个请求的延迟
这正是 GQA/MQA 等 KV Cache 压缩技术的重要性所在 — 缩小 KV Cache 后可以支持更大的 batch size,从而提升 Decode 阶段的效率。
实际性能影响:TTFT vs TPS
两个阶段分别对应不同的用户体感指标:
TTFT — Time To First Token
定义:从用户发送请求到收到第一个生成 token 的时间。
TTFT 主要由 Prefill 阶段决定。影响因素:
- Prompt 长度:prompt 越长,Prefill 计算量越大,TTFT 越高
- GPU 算力:Prefill 是 compute-bound,更快的 GPU 直接缩短 TTFT
- Prefill 计算量与 prompt 长度近似线性(Attention 部分是二次的,但通常 FFN 主导)
TPS — Tokens Per Second
定义:Decode 阶段每秒生成的 token 数量。
TPS 由 Decode 阶段决定。影响因素:
- 内存带宽:Decode 是 memory-bound,带宽越高 TPS 越快
- 模型大小:参数越多,每步需要加载的权重越多
- KV Cache 大小:序列越长,Attention 步骤加载的数据越多
数值估算
以 LLaMA-2 7B(约 bytes FP16)在 A100 上为例:
Decode TPS 估算(memory-bound,忽略 KV Cache):
实际受 KV Cache 加载、内核启动开销等因素影响,真实值通常在 100-130 tokens/s 左右(batch size = 1)。
Prefill 速度估算(compute-bound):
即 Prefill 处理 prompt 的吞吐量可以达到 Decode 的 100 倍以上 — 这就是为什么你感受到”等一下后快速输出”而不是”均匀缓慢输出”。
优化方向
针对两个阶段不同的计算特性,业界发展出了不同的优化策略:
Prefill 优化
- Flash Attention:虽然 Prefill 整体是 compute-bound,但标准 Attention 实现会将 的中间矩阵反复写入/读回 HBM,产生大量不必要的显存访问。Flash Attention 通过分块在 SRAM 中完成 softmax 和矩阵乘,避免中间矩阵落盘,将 Attention 部分的 HBM 访问从 降至
- Tensor Parallelism:将矩阵运算分布到多个 GPU,提升 compute-bound 操作的吞吐量
- 量化(Quantization):使用 INT8/FP8 降低精度,在相同硬件上获得更高的有效算力
Decode 优化
- KV Cache 压缩:GQA、MQA 减少 KV Cache 大小,降低内存带宽需求
- Speculative Decoding(推测解码):用小模型快速”猜”多个 token,再用大模型一次验证,将多步 Decode 合并为一次 Prefill-like 的并行验证
- Continuous Batching:动态组 batch,提升 GPU 利用率
混合优化
- Chunked Prefill:将长 prompt 分块处理,在 Prefill 的间隙穿插 Decode 步骤,避免长 prompt 的 Prefill 阻塞其他请求的 Decode
- Disaggregated Serving(分离式推理):将 Prefill 和 Decode 部署到不同的硬件上 — Prefill 用计算密集型 GPU,Decode 用高带宽设备
推荐学习资源
如果你想更深入地学习 LLM 推理优化,以下是我们精选的资源:
经典论文
- Kwon et al.《Efficient Memory Management for Large Language Model Serving with PagedAttention》 — vLLM 核心论文(SOSP 2023),提出用类似 OS 虚拟内存的方式管理 KV Cache,实现近零浪费。是理解现代 LLM serving 内存管理的核心论文。
- Lilian Weng《Large Transformer Model Inference Optimization》 — 系统性综述 Transformer 推理优化方法,涵盖蒸馏、量化、剪枝、稀疏化、架构优化等,是推理优化领域的最佳综述之一。
博客与教程(图文并茂)
- kipply《Transformer Inference Arithmetic》 — 推理性能分析的经典博文。从第一性原理推导 LLM 推理延迟,详解 KV Cache 机制、模型并行、batch size 影响、FLOPS 计算、memory bandwidth bound vs compute bound 的判断方法。
- Patrick von Platen / Hugging Face《Optimizing your LLM in production》 — 涵盖低精度推理(8-bit/4-bit)、Flash Attention、KV Cache 优化(MQA/GQA)、位置编码等,包含详细的内存计算和加速比数据,实操性强。
- Anyscale《How continuous batching enables 23x throughput in LLM inference》 — 详解 continuous batching 机制,对比 static batching 的吞吐量差异(高达 23 倍),benchmark 了 HF TGI、vLLM、Ray Serve 等框架的实际性能。
- Finbarr Timbers《How is LLaMa.cpp possible?》 — 分析 LLM 在消费级硬件上推理的可行性原理。通过数学推导展示 memory bandwidth 是瓶颈、量化如何大幅降低内存需求。含不同设备(A100/M1/M2)的性能计算对比。
总结
| 概念 | 说明 |
|---|---|
| Prefill 阶段 | 并行处理完整 prompt,生成 KV Cache,compute-bound |
| Decode 阶段 | 自回归逐 token 生成,读取 KV Cache,memory-bound |
| Arithmetic Intensity | Prefill: (高) vs Decode: (低) |
| Roofline 模型 | AI 为 compute-bound,反之为 memory-bound |
| TTFT | Time To First Token,由 Prefill 决定 |
| TPS | Tokens Per Second,由 Decode 决定 |
| 核心矛盾 | Decode 的 AI 远低于硬件平衡点,GPU 算力严重浪费 |
核心直觉:LLM 推理的两个阶段就像”备菜”和”上菜”。Prefill 像厨师同时处理所有食材(并行、计算密集),速度取决于厨师的刀工速度(GPU 算力)。Decode 像服务员一道道上菜(串行、带宽密集),速度取决于厨房到餐桌的传送带速度(内存带宽)。理解这个区别,是理解一切 LLM 推理优化技术的起点。