01. Prefill 和 Decode 有什么区别?各自的瓶颈是什么?

整理 Prefill 与 Decode 的区别、瓶颈与优化启发。

简单回答

Prefill(预填充)是处理用户输入 Prompt 的阶段,一次性并行计算所有输入 token 的 KV Cache;Decode(解码)是逐 token 生成输出的阶段,每次只生成一个 token。Prefill 是计算密集型(Compute-bound),瓶颈在 GPU 算力;Decode 是访存密集型(Memory-bound),瓶颈在显存带宽。理解这个区别是做推理优化的基础。

详细解释

自回归生成的两个阶段

大模型的推理过程天然分成两个阶段,性质完全不同。

Prefill 阶段处理用户的输入 Prompt。假设 Prompt 有 1000 个 token,Prefill 会把这 1000 个 token 一次性送进模型,并行计算所有层的 Attention 和 FFN,为每个 token 生成 KV(Key-Value)并缓存下来。这一步的计算量很大——1000 个 token 之间要做 full attention( 复杂度),但因为是并行计算,GPU 的算力可以被充分利用。所以 Prefill 阶段是计算密集型的,瓶颈在于 GPU 的 FLOPS(浮点运算能力)。

Decode 阶段是逐 token 生成输出。每一步只生成一个新 token,这个 token 需要和之前所有 token 的 KV Cache 做 Attention 计算,然后经过 FFN 得到 logits,采样出下一个 token。虽然只处理一个 token,但每一步都要从显存中读取整个 KV Cache(可能几个 GB)和全部模型参数,计算量相对于数据搬运量来说很小。所以 Decode 阶段是访存密集型的,瓶颈在于 GPU 的显存带宽(HBM Bandwidth)。

一个直观的感受:用户提交一个长 Prompt 后,通常会等一小段时间(Prefill),然后开始看到回复一个字一个字地蹦出来(Decode)。Prefill 的等待时间叫 TTFT(Time To First Token),是用户体验的关键指标。

为什么 Decode 是访存密集型

这一点值得展开理解。在 Decode 阶段,每生成一个 token,模型需要做什么?

对于一个 7B 参数的模型(FP16,约 14GB),每生成一个 token 需要把全部 14GB 的模型权重从显存读入计算单元(因为每一层的 Attention 和 FFN 都要算一遍)。还要读取 KV Cache——如果上下文已经有 2000 个 token,每层都有对应的 K 和 V,总量可能是几百 MB 到几 GB。

但实际的计算量呢?一个 token 和模型参数做矩阵乘法,FLOPS 大约是参数量的 2 倍,7B 模型就是约 14 GFLOPS。一块 A100 的算力是 312 TFLOPS(FP16),14 GFLOPS 只占算力的不到 0.005%。但 A100 的 HBM 带宽是 2TB/s,读 14GB 参数需要 7ms——这才是真正的时间开销。

所以 Decode 阶段 GPU 大部分时间在等数据从显存搬到计算单元,算力严重闲置。这就是为什么说 Decode 是 Memory-bound 的。

对优化的指导意义

理解了这个区别,很多优化技术的原理就变得清晰了。

KV Cache 就是为了避免 Decode 阶段的重复计算——如果不缓存 KV,每生成一个 token 都要重新计算之前所有 token 的 KV,那 Decode 阶段也变成计算密集型了,但延迟会非常高。

量化(INT8、INT4)主要受益在 Decode 阶段——参数变小意味着从显存读取的数据量减少,直接缓解访存瓶颈。对 Prefill 的加速效果相对小一些(因为 Prefill 是计算瓶颈,量化减少的主要是访存量)。

Speculative Decoding 的动机也来自于此——Decode 阶段 GPU 算力严重闲置,不如让一个小模型先"猜"几个 token,大模型一次性并行验证(利用 Prefill 模式的并行性),用多余的算力换取更少的 Decode 步数。

Batching 在 Decode 阶段特别有价值——一个 token 的 Decode 和一批 token 的 Decode,读取模型权重的量是一样的(都要读一遍全部参数),但一批 token 的计算量更大,GPU 利用率更高。

Prefill 和 Decode 的解耦

在生产部署中,Prefill 和 Decode 的负载特征不同(一个计算密集、一个访存密集),一些先进的推理系统会把两者分开调度甚至分开部署在不同的 GPU 上——用高算力的 GPU 做 Prefill,用高带宽的 GPU 做 Decode。DeepSeek 的推理系统就采用了 Prefill-Decode 分离的架构。这种做法可以更好地匹配硬件资源,但系统设计复杂度也大幅增加。

面试时可以这样答

大模型推理分 Prefill 和 Decode 两个阶段。Prefill 处理输入 Prompt,所有 token 并行计算,生成 KV Cache。Decode 逐 token 生成输出,每步只算一个 token 但要读取全部模型参数和 KV Cache。

关键区别在性能瓶颈。Prefill 是计算密集型,瓶颈在 GPU 算力。Decode 是访存密集型,瓶颈在显存带宽——每生成一个 token 要从显存读十几 GB 的参数,但实际计算量只占算力的零点几,GPU 大部分时间在等数据搬运。

理解这个区别是理解所有推理优化技术的基础。量化主要缓解 Decode 的访存瓶颈。Batching 提高 Decode 阶段的 GPU 利用率。Speculative Decoding 利用 Decode 阶段闲置的算力。KV Cache 避免 Decode 的重复计算。生产上甚至会把 Prefill 和 Decode 拆开部署在不同硬件上。

常见追问

  1. Prefill 阶段的计算复杂度和 Prompt 长度是什么关系?
  2. 为什么 Batch Size 增大对 Decode 延迟的影响比对 Prefill 小?
  3. Prefill-Decode 分离架构在工程上怎么实现?