大模型推理预填充与解码两阶段详解

作者:暴富20212026.11.03 22:02浏览量:0

简介:本文系统讲解大语言模型推理中Prefill与Decode两个核心阶段的原理、差异与工程实践,帮助开发者理解计算密集型与访存密集型的本质区别,掌握KV Cache机制、批处理策略与性能优化方法,从而更高效地完成推理服务的部署、调优与问题排查。

大语言模型推理的两个核心阶段:Prefill(预填充)与 Decode(解码)详解

一、教程目标

本教程旨在帮助读者系统理解大语言模型(LLM)推理过程中 Prefill(预填充) 与 Decode(解码) 两个核心阶段的工作原理、计算特征与工程差异。通过本教程,读者将能够:

  • 清晰区分两个阶段在矩阵计算、内存访问、GPU 利用率方面的本质不同;
  • 理解 KV Cache 在解码阶段的作用与实现逻辑;
  • 掌握针对不同阶段进行性能优化的通用思路;
  • 具备在实际推理服务部署中定位瓶颈、排查异常的初步能力。

本教程适合大模型应用开发者、推理服务运维人员、技术负责人以及对 LLM 底层机制感兴趣的工程师阅读。阅读前建议具备 Transformer 注意力机制、矩阵乘法、GPU 并行计算等基础知识。


二、适用场景

理解 Prefill 与 Decode 的差异,在以下场景中尤为关键:

  • 推理服务部署:需要根据请求特征(长提示词、长输出)配置合理的批处理与显存策略;
  • 性能调优:定位首 Token 延迟(TTFT)与单 Token 输出延迟(TPOT)瓶颈;
  • 成本控制:评估计算资源与显存资源的使用比例,优化硬件选型;
  • 容量规划:估算并发请求数、上下文长度对显存和吞吐的影响;
  • 问题排查:当出现显存溢出、吞吐骤降或延迟抖动时,判断问题出在哪个阶段。

三、前置准备

在深入阶段细节之前,需要明确以下前置概念与条件:

  1. Transformer 解码器结构基础知识:了解自注意力、前馈网络、层归一化的基本组成;
  2. 注意力机制中的 Q、K、V 概念:Query(查询)、Key(键)、Value(值)三组向量的来源与作用;
  3. 矩阵乘法的计算特性:理解大规模矩阵乘法为何适合并行计算;
  4. GPU 计算模型的基本认知:了解计算单元、显存带宽、访存延迟的基本概念;
  5. KV Cache 的基本思想:缓存历史 Token 的 Key 和 Value,避免重复计算。

若上述概念尚不熟悉,建议先补充相关知识再阅读本教程,效果更佳。


四、实施步骤

步骤一:理解自回归生成的整体流程

大语言模型生成文本采用自回归方式:每次根据已有的 Token 序列预测下一个 Token,然后将新 Token 追加到序列中,继续预测,直到遇到结束符或达到最大长度。

这个流程天然分为两段:

  • 第一段:处理用户输入的完整提示词(Prompt),一次性计算出所有输入 Token 的表示,并生成第一个输出 Token;
  • 第二段:基于第一个输出 Token,逐个生成后续 Token,每步只处理一个新 Token。

第一段对应 Prefill,第二段对应 Decode。理解这一划分,是理解后续所有差异的前提。

步骤二:分析 Prefill 阶段的计算特征

在 Prefill 阶段,模型一次性接收长度为 n 的输入序列,需要为每个位置计算 Query、Key、Value 向量,并完成注意力计算:

  1. Q = X · W_q
  2. K = X · W_k
  3. V = X · W_v
  4. Attention = softmax(Q · Kᵀ / √d_k) · V

其中 Q · Kᵀ 是一个 n × n 的注意力分数矩阵。当 n 较大时,这个矩阵乘法的规模非常可观。同时,各层的线性变换(如 X · W_q)也是大规模矩阵乘法。

关键结论:Prefill 阶段包含大量可以并行执行的矩阵运算,GPU 的众多计算核心能够被充分调度,因此它属于计算密集型(Compute-bound)任务。计算单元利用率高,显存带宽往往不是瓶颈。

工程含义:Prefill 阶段的耗时与输入长度呈近似平方或线性增长关系,长提示词会显著拉高首 Token 延迟。

步骤三:分析 Decode 阶段的计算特征

进入 Decode 阶段后,假设模型已经处理到第 t-1 个 Token,现在需要处理第 t 个 Token。此时模型只需要计算当前 Token 的 q_t、k_t、v_t,并与之前保存的 KV Cache 结合,完成注意力计算:

  1. h_t = softmax(q_t · [K_cache; k_t]ᵀ / √d_k) · [V_cache; v_t]

其中:

  • K_cache、V_cache:保存了前 t-1 个 Token 的 Key 和 Value;
  • k_t、v_t:当前 Token 新计算得到的 Key 和 Value;
  • [K_cache; k_t] 表示在序列维度上的拼接。

关键结论:Decode 阶段每次只处理一个 Token,矩阵乘法的维度极小(例如 1 × d 与 d × d 相乘),无法填满 GPU 的大量计算核心。但每一步都需要读取整个 KV Cache 以及模型权重,数据搬运量远大于计算量。因此它属于访存密集型(Memory-bound)任务,瓶颈在显存带宽而非算力。

工程含义:Decode 阶段单步延迟受显存带宽限制明显,且随上下文长度增长而增加,因为需要读取更长的 KV Cache。

步骤四:对比两阶段的核心差异

维度 Prefill Decode
处理 Token 数 一次处理 n 个 一次处理 1 个
矩阵规模 大矩阵乘法 小矩阵向量乘
瓶颈类型 计算密集型 访存密集型
GPU 利用率 高 低,算力闲置
主要延迟指标 首 Token 延迟(TTFT) 单 Token 输出延迟(TPOT)
对上下文敏感度 输入长度影响大 上下文长度影响缓存读取
优化重点 并行度、算子融合 显存带宽、批处理、缓存管理

理解这张对比表,是后续做推理优化和容量规划的基础。

步骤五:掌握 KV Cache 的作用与管理

KV Cache 是 Decode 阶段能够高效运行的关键机制。若没有缓存,每生成一个新 Token 都要重新计算全部历史 Token 的 K、V,计算量将随序列长度线性增长,完全不可接受。

KV Cache 的核心逻辑:

  1. Prefill 阶段:计算并保存所有输入 Token 的 K、V,写入缓存;
  2. Decode 阶段:每步只计算当前 Token 的 k_t、v_t,追加到缓存,然后与全部历史 K、V 做注意力;
  3. 缓存增长:缓存大小与序列长度成正比,长上下文会占用大量显存。

显存估算思路(通用公式):

  1. KV Cache 显存 ≈ 2 × 层数 × 头数 × 头维度 × 序列长度 × 批大小 × 数据类型字节数

在实际部署中,需要根据模型规模、上下文长度上限和并发数,合理预留显存,避免 OOM。

步骤六:设计针对性的优化策略

针对 Prefill 的优化方向:

  • 算子融合:将多个线性变换与激活操作融合,减少核函数启动开销;
  • 注意力优化:采用分块计算、稀疏注意力等减少 n × n 矩阵的内存占用与计算量;
  • 批处理:将多个请求的 Prefill 合并,提高 GPU 利用率;
  • 并行策略:在超长输入场景下,采用序列并行或张量并行分摊计算。

针对 Decode 的优化方向:

  • 连续批处理(Continuous Batching):动态将新请求插入正在运行的批次,提高每步的批大小,摊薄访存开销;
  • KV Cache 量化与压缩:降低缓存精度或压缩存储,减少显存带宽压力;
  • 分页缓存管理:以块为单位管理缓存,减少碎片,提高显存利用率;
  • 投机解码:用小模型或草稿模型预测多个 Token,再由主模型验证,减少主模型前向次数。

通用优化建议:

  • 监控 TTFT 与 TPOT 两个指标,分别对应两个阶段的健康度;
  • 根据业务特征(长输入短输出 / 短输入长输出)配置不同的批处理与缓存策略;
  • 在资源受限环境中,优先保证 Decode 阶段的显存带宽,因为它是持续输出阶段的主要瓶颈。

步骤七:结果验证

部署或调优后,可通过以下方式验证效果:

  1. 指标采集:分别统计 Prefill 阶段耗时(TTFT)与 Decode 阶段平均单 Token 耗时(TPOT);
  2. 吞吐对比:在相同并发下对比优化前后的每秒输出 Token 数;
  3. 显存监控:观察 KV Cache 占用的显存峰值,确认未接近上限;
  4. 压力测试:构造长输入、长输出、混合负载等场景,观察延迟抖动;
  5. 瓶颈定位:若 Prefill 慢,检查计算利用率;若 Decode 慢,检查显存带宽与批大小。

五、常见问题与排查

问题一:首 Token 延迟过高。
原因通常是 Prefill 阶段计算量大,尤其是长提示词。排查方向:确认输入长度分布,是否可做提示词压缩、前缀缓存复用;检查是否启用了高效注意力算子。

问题二:输出阶段每 Token 延迟随上下文增长明显。
原因是 Decode 阶段需读取更长的 KV Cache。排查方向:确认缓存是否量化、是否存在重复读取;评估是否可通过滑动窗口注意力或缓存淘汰策略控制长度。

问题三:显存溢出(OOM)。
通常是 KV Cache 占用过大,常见于长上下文或高并发。排查方向:估算缓存显存公式,检查批大小与最大长度配置,考虑缓存量化或分页管理。

问题四:GPU 利用率忽高忽低。
Prefill 阶段利用率高,Decode 阶段利用率低,属于正常现象。若整体利用率持续偏低,可能是批处理策略未优化,考虑启用连续批处理。

问题五:吞吐上不去。
若 Decode 是瓶颈,通常是批大小不足或访存受限;若 Prefill 是瓶颈,可能是算子效率低或并行度不够。需分阶段测量后再决定优化方向。


六、优化建议

  • 性能:将 Prefill 与 Decode 分离部署,可针对不同瓶颈选型硬件,例如 Prefill 侧重算力、Decode 侧重显存带宽;
  • 稳定性:为 KV Cache 设置合理的上限与淘汰策略,避免突发长请求导致整体服务不可用;
  • 可维护性:将两阶段的指标独立监控,便于快速定位回归;
  • 成本控制:根据业务输入输出比例,动态调整资源配比,避免为单一阶段过度配置;
  • 安全:缓存中可能包含用户敏感上下文,需做好隔离与生命周期管理。

七、总结

本教程围绕大语言模型推理的两个核心阶段展开:

  • Prefill 一次性处理完整输入,包含大规模矩阵乘法,属于计算密集型任务,决定首 Token 延迟;
  • Decode 逐 Token 生成输出,依赖 KV Cache,属于访存密集型任务,决定持续输出速度。

两者在计算特征、瓶颈类型和优化手段上差异显著。理解这些差异,是进行推理服务部署、性能调优、容量规划与问题排查的基础。后续可继续关注连续批处理、缓存压缩、投机解码等方向,进一步提升推理效率与资源利用率。