模型部署与推理优化

Prefill 与 Decode:Transformer 推理的两阶段

kp-003核心20 分钟01-全景与度量

一句话定义

一次 LLM 推理由 Prefill(并行处理全部输入 token)与 Decode(逐 token 自回归生成)两个阶段组成,前者计算密集、后者访存密集,几乎所有推理优化都源于对这个不对称的正确处理。

为什么重要

两阶段瓶颈不同,优化药方完全相反:给 prefill 提速要靠算力与注意力 kernel(FlashAttention),给 decode 提速要靠减少读取量与提高读取复用(量化、批处理)。混为一谈会导致"优化了半天打错了靶子"——这是本领域最常见的方法论错误。

前置知识

  • Transformer 每层 = 注意力 + FFN,自回归生成逐 token 进行(最小回顾即可)。
  • kp-001(两条优化主线)。

核心概念

  • Prefill 阶段:把 prompt 的 n 个 token 一次并行喂入,产出第一个输出 token,同时生成全部 token 的 K/V 写入 KV Cache。n 个 token 共享大量矩阵乘,算术强度高 → 计算密集(compute-bound)。
  • Decode 阶段:每步只处理 1 个新 token,但要把全部权重和已有 KV Cache 从显存读一遍,算术强度低 → 访存密集(memory-bound)。
  • 算术强度(Arithmetic Intensity):FLOPs / 读取字节数,判断瓶颈的量尺。
  • Roofline 判据:实际用时 ≈ max(计算时间, 访存时间),取上界的那一项是瓶颈。

原理与机制

Prefill 把 n 个 token 压进同一批矩阵乘,算术强度随并行度上升直到触及算力上限;decode 每步只引入 1 个 token 的新计算,却要为它把全部权重与历史 KV 从显存搬一遍,算术强度恒定在低位。因此 prefill 的加速靠"算得更稠密"(更好的 kernel、更高的并行),decode 的加速靠"读得更少、共享得更多"(量化、批处理、KV 压缩)——本库后续所有技术都由此分流。

公式与模型

decode 单步时间下界(权重读取主导):

Tdecode ≈ BytesweightsBWmem, 单流速度 = 1Tdecode

可复现估算:7B 模型 FP16 权重 14GB,A100 带宽约 2TB/s,则 T_decode ≈ 14GB / 2000GB/s = 7ms,单流 decode 上限约 143 tokens/s——与实测 100–150 tokens/s 吻合,验证了"瓶颈是读权重"。

batch=B 时的拐点:访存时间几乎不随 B 变化(权重一次读入、复用 B 次),计算时间随 B 线性增长,两者相等处的临界 batch B = (Bytes/BW) × FLOPS / (2N)。对 7B/A100(FP16 算力 312 TFLOPS)估算 B ≈ 150:批小于它时是访存瓶颈(该加批),批大于它时是算力瓶颈(该减批或上量化)。

图示

        prefill(一次)            decode(×N)
输入 512 tok ──► [并行大矩阵乘] ──► 生成 t1
                                  └► t1 ─► [1 tok × 全权重+KV 读取] ─► t2 ─► …
瓶颈:      算力(FLOPS)                显存带宽(GB/s)
优化:      FlashAttention/chunked     量化/批处理/KV压缩/投机解码

直观类比

Prefill 像一次搬一整车货(满载,讲究装卸效率);Decode 像每分钟去仓库取一件货(瓶颈是路途而不是搬运能力)——提高效率的办法要么把货变小(量化),要么一次顺路捎多家的货(批处理)。

实例或案例

长文档摘要(输入 8k、输出 200):TTFT 由 prefill 主导,FlashAttention 与 chunked prefill 收益最大;而闲聊机器人(输入 50、输出 800)的体验由 decode 主导,量化与投机解码收益最大。同一引擎同一模型,两个场景的优化清单完全不同。

常见误区

  • "GPU 利用率高 = 系统高效":decode 时算力大量空转,利用率指标反而虚高(SM 被访存占着),它不是好容量指标。
  • 以为 prefill 也是逐 token 进行的:实际上 prompt 是一次并行计算,这正是 TTFT 通常远小于"输入长度 × TPOT"的原因。
  • 用 CPU 时延直觉套 GPU:GPU 上"算得慢"多半是"读得慢"。

自测题

  1. 判断瓶颈:7B FP16、batch=1、单流 decode 22 tokens/s,为什么远低于算力上限?

要点:每步读 14GB 权重,2TB/s 带宽给出约 7ms/步下限 ≈ 143 tokens/s 上限,实测受 kernel 效率进一步压低;瓶颈是带宽。

  1. 为什么 prefill 是计算密集的?

要点:n 个 token 并行参与矩阵乘,算术强度高,时间由 FLOPS 主导。

  1. batch 从 1 提到 64,单步 decode 时间大约怎么变?

要点:权重读取不变、计算量 ×64,在未到 B* 前时间几乎不变——这就是批处理"免费"提吞吐的原因。

与其他知识点的关系

kp-004 在两阶段之上建立显存账本;kp-013 的 KV Cache 是 decode 结构的必然产物;kp-021 的连续批处理本质是把 decode 的"读取复用"做到极致;kp-024 把两阶段拆到不同机器。

延伸阅读

《Efficient Memory Management for Large Language Model Serving with PagedAttention》第 2 节对两阶段不对称有定量分析。

#Prefill#Decode#计算密集#访存密集#roofline