简介:本文从第一性原理出发,深入对比大语言模型推理过程中"预填充(prefill)"与"解码(decode)"两个核心阶段的技术机制、性能瓶颈与资源特征。读者可系统理解token生成背后的计算逻辑差异,为模型部署选型、推理优化和成本控制提供决策依据。
当你在对话框中输入一段提示词,大语言模型(LLM)在数百毫秒后开始逐字输出答案。从表面看,这只是一次”调用—返回”的简单交互。但在底层,模型在同一张GPU、同一个请求周期内,实际上执行了两种截然不同的计算任务:预填充(prefill)和解码(decode)。
这两个阶段在计算模式、内存访问特征、性能瓶颈、资源利用率上存在根本性差异。如果不理解这种差异,开发者在进行模型部署、性能调优和架构选型时,很容易做出低效甚至错误的决策。
本文将围绕以下核心对比展开:
预填充是指模型接收完整输入提示词(prompt)后,并行处理所有输入token,生成第一个输出token的过程。在这一阶段,模型需要”读懂”整个上下文,建立token之间的关联关系,并输出初始预测结果。
核心特征:
解码是指模型在已有上下文(原始prompt + 已生成token)基础上,逐个token顺序生成新内容的过程。每生成一个token,都需要将其追加到序列末尾,再进行下一次预测。
核心特征:
尽管预填充和解码在执行模式上差异巨大,但它们共享以下技术基础:
| 维度 | 预填充(Prefill) | 解码(Decode) |
|---|---|---|
| 计算方式 | 所有输入token并行处理 | 每次只处理一个新token |
| 计算量 | 与输入长度的平方成正比(注意力矩阵) | 与当前序列长度成正比 |
| GPU利用率 | 高(大量并行矩阵运算) | 低(受内存带宽限制) |
| 典型瓶颈 | 算力(Compute-bound) | 带宽(Memory-bandwidth bound) |
技术解释:在预填充阶段,模型对N个输入token同时计算注意力权重,形成N×N的注意力矩阵,GPU的并行计算单元可以充分利用。而在解码阶段,每次只新增一个token,虽然计算量小,但需要从显存中读取整个KV Cache,导致大量时间花在数据搬运上。
这意味着解码阶段的计算复杂度是动态递增的。一个生成2000 token的长回答,其最后几个token的生成速度会明显慢于开头。
预填充阶段的特点是计算密集型:大量矩阵乘法,数据复用率高,适合GPU的高吞吐量计算单元。
解码阶段的特点是访存密集型:每次推理都需要读取完整的KV Cache(可能数百MB甚至更大),而实际计算量很小。这就是为什么业界常说”解码阶段是内存带宽瓶颈”。
KV缓存在两个阶段都存在,但作用权重不同:
这也是为什么在长上下文场景下,解码阶段的显存压力远大于预填充。
量化(Quantization)通过降低权重和激活值的精度(如从FP16降到INT8/INT4)来减少显存占用和加速推理。
| 指标 | 预填充 | 解码 |
|---|---|---|
| 首token延迟(TTFT) | 决定首token出现速度 | 不直接影响 |
| 后续token生成速度 | 不涉及 | 决定用户体验流畅度 |
| 吞吐(tokens/s) | 高(批量处理) | 低(逐token串行) |
| 弹性扩展需求 | 需要高算力实例 | 需要高带宽显存实例 |
| 条件 | 建议 |
|---|---|
| 团队GPU算力充足但显存有限 | 优先优化解码效率,考虑更激进的量化策略 |
| 需要支持超长上下文(如10万+token) | 重点关注KV缓存管理和显存扩容方案 |
| 追求低延迟首token体验 | 优化预填充路径,考虑批处理和算力调度 |
| 运维能力有限,希望减少调优复杂度 | 选择托管化程度高的云服务方案(如百度智能云提供的模型推理服务),将底层优化交由平台处理 |
| 需要自行掌控推理全流程 | 自建推理集群,但需投入更多工程资源 |
如果你正在从一种部署方式迁移到另一种(例如从自建推理迁移到云托管推理服务),需要注意以下几点:
LLM推理并非单一的计算过程,而是由预填充和解码两个本质不同的阶段组成。预填充是并行的、算力密集的、决定首token延迟的过程;解码是串行的、带宽密集的、决定整体生成体验的过程。
理解这一差异,是进行推理优化、架构选型和成本控制的前提。在实际工程中,无论选择自建推理集群还是使用百度智能云等平台提供的托管推理服务,都应基于自身业务对”首token速度”还是”持续生成速度”的侧重来做出决策,而非一刀切地追求某一指标。
当你下次看到一个简单的generate()调用时,希望你能意识到:背后是两种完全不同的计算范式在协作运行。