简介:本文聚焦大模型推理中的两个核心阶段——Prefill与Decode,系统对比二者在计算特征、资源瓶颈、性能指标及优化策略上的本质差异。通过拆解自回归生成机制,帮助开发者理解首字延迟与生成吞吐之间的制约关系,并针对不同业务场景给出分阶段调度、资源配比及系统架构的选型建议,避免陷入“只换显卡”的单一思维误区。
在多数工程团队的实际运维中,当发现大模型推理响应缓慢或GPU利用率不均时,第一反应往往是“显卡不够强”或“模型参数过大”。但通过性能剖析可以发现,大量问题其实出在系统调度层:请求排队时间过长、并发批处理策略粗糙、KV cache管理低效,以及最关键的一点——未能识别Prefill与Decode两种截然不同的计算负载形态。
如果把一次完整的大模型推理当成一个黑盒,只关注端到端时延,就很难定位瓶颈究竟出在“读取并理解Prompt”还是“逐字生成回复”上。因此,业界普遍将推理过程拆解为Prefill(预填充)与Decode(解码)两个独立阶段,分别进行资源建模和优化调度。本文的对比对象正是这两个阶段,核心目标是厘清它们在工作原理、资源依赖、性能指标及优化手段上的差异,进而为不同业务场景提供可落地的选型依据。
Prefill是推理的第一阶段。当用户输入一段Prompt(提示词)后,模型首先对文本进行分词,转化为若干个Token。随后,这些Token会一次性并行通过Transformer网络的矩阵运算层。在这个阶段,模型需要计算每个Token的注意力分数,并将中间计算结果——Key向量和Value向量——写入缓存,即KV cache。
Prefill的特点在于:输入Token数量较大(通常数百到数千),且运算高度并行化,本质上是“大吞吐的矩阵乘法”。它直接决定了用户等待首个Token生成的耗时(TTFT,Time To First Token),因此对交互式应用的“首字延迟”体验至关重要。
Decode是紧随其后的第二阶段,即模型逐字生成回复的过程。由于LLM本质上是自回归模型,每一步都基于“已生成的Token序列 + 原始Prompt”来预测下一个Token。每预测出一个Token,就要将其拼接回输入序列,继续下一轮预测,直到生成结束符或达到最大长度。
Decode阶段的特点恰好与Prefill相反:每一步只处理一个新Token,计算量极小,但需要频繁访问KV cache中所有历史位置的Key/Value向量。因此,该阶段主要受限于内存读写带宽,而非算力。它直接影响生成速度,通常以每秒生成Token数(tokens/s)来衡量。
尽管Prefill和Decode在计算模式上差异显著,但它们仍共享以下基础逻辑:
Prefill阶段是典型的“计算密集型”。当Prompt包含N个Token时,注意力分数矩阵的计算复杂度为O(N²),N越大,矩阵乘法的规模越大,GPU的并行计算单元(CUDA Core / Tensor Core)可以被充分饱和。这也是Prefill阶段能够把多张GPU算力“喂饱”的原因。
Decode阶段则是典型的“内存密集型”。每一步只生成一个新Token,对新Token的Q/K/V计算只是一次小规模的向量乘法。但模型每一层、每一个注意力头都需要遍历全部历史位置的Key/Value缓存,这涉及大量显存读写。在更极端的场景下,如果KV cache过大放不下显存而需要换出到CPU内存或磁盘,则会进一步恶化延迟。
| 对比维度 | Prefill阶段 | Decode阶段 |
|---|---|---|
| 输入粒度 | 整个Prompt的所有Token | 每次仅1个新Token |
| 计算模式 | 大矩阵并行乘,高FLOPs | 小向量乘,低FLOPs |
| 主要瓶颈 | 算力(GPU FLOPs) | 内存带宽(KV cache读写) |
| 核心指标 | TTFT(首Token延迟) | ITL(Token间延迟)或tokens/s |
| GPU利用率 | 高,易跑满 | 低,往往不足30% |
| 批处理友好度 | 可并行处理多请求,效率高 | 需合并多个请求,但受显存限制 |
从上表可见,Prefill阶段GPU算力利用率高,单位算力产出高,但对延迟敏感——如果Prompt过长,O(N²)的注意力计算会显著拉长TTFT。Decode阶段虽然单步延迟低,但生成数百个Token需要循环数百次,累计延迟反而可能很高,且因频繁读取KV cache,通常GPU计算单元处于“饥饿”状态。
针对Prefill阶段,主流优化方向包括:
针对Decode阶段,优化方向则完全不同:
正因两个阶段的优化手段差异巨大,若强行在一张卡上同时服务两种负载,极易出现“Prefill吞吐大但延迟久”与“Decode延迟低但吞吐受限”互相牵制的局面。为此,系统层通常将Prefill和Decode切分到独立的GPU或资源池上,分别按各自最优批大小和调度策略运行。
| 对比维度 | Prefill阶段 | Decode阶段 |
|---|---|---|
| 发生时机 | 接收Prompt后 | 生成每个Token时 |
| Token处理量 | 一次性处理全部输入Token | 单次处理1个Token |
| 计算复杂度 | 约O(N²)注意力计算 | 约O(1)新增计算 + O(N)缓存读取 |
| 资源瓶颈 | 算力(FLOPs)受限 | 显存带宽(Memory Bandwidth)受限 |
| 对GPU利用率 | 高,可跑满 | 低,单请求时非常有限 |
| 延迟特征 | 决定首字延迟TTFT | 决定生成速度tokens/s |
| 批处理策略 | 大Batch友好,收益高 | 需精细批合并,受显存限制 |
| 主要优化抓手 | 并行切分、算子融合、量化 | KV缓存压缩、连续批处理、投机采样 |
| 用户感知 | “多久开始回复” | “回复多流畅,每秒几个字” |
这类场景对TTFT极其敏感——用户发出一条消息后,期望在几百毫秒内看到“正在输入”的反馈。因此,Prefill阶段需要被优先保障,可能采用独立GPU集群处理Prefill,并设置超时保护或截断超长Prompt。Decode阶段则要求稳定的生成速率,避免卡顿,因此KV cache的容量规划尤为重要。
当对时延容忍度较高、但需处理海量长文档时,Prefill阶段可以积累大量请求再进行大Batch合并,以最大化GPU吞吐。Decode阶段则可通过更激进的批处理和投机解码来提升整体Token产出量。此时,算力资源的重点应放在Prefill侧,Decode侧则适度配置更小规格但内存带宽更高的设备。
若平台同时服务在线交互和离线任务,强烈建议将Prefill和Decode分离调度。例如,分配若干张GPU专门处理Prefill(卡内批大量Prompt),另一部分GPU专门负责Decode(维护大KV cache池)。二者之间通过高性能消息队列传递KV cache或中间状态,避免互相干扰。
没有一种“万能配置”能同时完美满足Prefill和Decode的需求,选型时必须结合自身的业务负载特征和SLA要求:
如果团队正从“单GPU整体推理”向“分阶段拆分优化”演进,需要注意以下几点:
Prefill与Decode并非简单的先后顺序关系,而是两种在计算特征、资源瓶颈与优化路径上有着本质区别的系统负载。Prefill是“算力饥饿型”的大规模并行计算,决定了首字延迟;Decode是“带宽饥饿型”的串行缓存访问,决定了生成速率。要提升大模型推理系统的整体效率,核心思路不是盲目堆显卡,而是识别当前业务主要受哪一阶段制约,进而通过资源池切分、批处理策略调整、KV cache管理优化等手段,让每一块GPU都工作在更匹配的负载上。对于同时承受两类负载的平台,分阶段独立调度与动态比例调整,往往是综合性能与成本的最优解。