尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

大模型推理加速:Prefill与Decode阶段深度解析与优化实践

大模型推理加速:Prefill与Decode阶段深度解析与优化实践 你肯定遇到过这种情况同一个大语言模型在第一次回答你的问题时响应得挺快但当你让它继续写下去或者进行多轮对话时后面的生成速度就明显变慢了甚至感觉有点“卡顿”。这不是你的错觉也不是模型“累了”。这背后是大语言模型推理过程中两个核心且截然不同的阶段在交替工作Prefill预填充和Decode解码。理解这两个阶段远不止是知道两个技术名词。它直接关系到你如何评估一个模型的真实性能、如何设计高效的提示词、如何为你的应用选择合适的推理框架甚至如何预估和优化服务成本。很多人会把大模型推理简单地看作一个“输入文本输出文本”的黑箱。但如果你拆开看Prefill 阶段像是模型的“热身”和“规划”它一次性处理完你给的所有输入提示词并准备好一个庞大的记忆库KV Cache而 Decode 阶段才是真正的“马拉松式创作”它依赖这个记忆库一个字一个字地“吐”出答案。这两个阶段的计算模式、资源消耗和瓶颈完全不同。混淆它们会导致很多实际工作中的误判。比如你可能用一个很短的提示词去测试模型觉得“速度很快”就认为它适合处理长文本生成任务。或者在部署服务时只关注吞吐量而忽略了延迟导致用户体验不佳。今天我们就彻底拆解 Prefill 和 Decode不仅说清“是什么”更要讲明白“为什么这样设计”以及在实际应用中“如何利用这个特性”和“需要避开哪些坑”。1. 从“一次性规划”到“逐字创作”Prefill 与 Decode 的本质区别要理解这两个阶段我们得先回到 Transformer 模型最核心的注意力机制。简单来说模型在生成每一个新词token时都需要“回顾”之前所有已生成的词以及你输入的提示词来计算当前最应该输出哪个词。这个“回顾”过程就是注意力计算。1.1 Prefill集中火力一次性构建“记忆宫殿”当你提交一段提示词例如“请用 Python 写一个快速排序函数”后推理过程的第一步就是 Prefill。它在做什么模型会并行地处理你输入的每一个 token。对于提示词中的每个位置模型都会计算其对应的 Key 和 Value 向量这就是著名的KV Cache的由来并将它们缓存起来。同时模型也会基于整个提示词上下文计算出第一个输出 token 的 logits可以理解为下一个词的概率分布。为什么能并行因为所有输入 token 对你来说都是已知的、固定的。模型可以像处理一个句子一样同时看到所有输入因此可以充分利用 GPU 的并行计算能力速度非常快。核心产出第一个待输出的 token例如“def”。一个为整个提示词构建好的、完整的KV Cache。你可以把它想象成模型为这段提示词精心准备的一个“记忆宫殿”或“参考资料库”后续生成再也不需要重新计算这些信息了。Prefill 阶段的特点是“短时、高并发、计算密集”。它的耗时与提示词长度大致呈线性关系。提示词越长构建这个“记忆宫殿”的时间就越长。1.2 Decode串行漫步从“记忆宫殿”中提取答案当 Prefill 阶段输出了第一个 token如 “def”后就进入了 Decode 阶段。它在做什么这是一个严格的串行过程。模型将刚刚生成的 token“def”作为新的输入追加到序列中。然后它只需要为这个最新的 token计算其 Key 和 Value并更新到 KV Cache 中。接着模型基于整个更新后的 KV Cache包含原始提示词和所有已生成词来计算下一个 token如 “quicksort”的概率。为什么是串行因为下一个词是什么取决于上一个词是什么。在生成“quicksort”之前你必须先有“def”。这种严格的因果依赖关系使得 Decode 无法并行处理多个“下一个词”的生成。它只能一个接一个地“吐”出 token。核心动作每次循环生成一个 token只做两件事为当前新 token 计算并更新 KV Cache增量更新。基于完整的 KV Cache通过一个矩阵乘法MatMul得到下一个 token 的 logits。Decode 阶段的特点是“长时、串行、内存带宽受限”。它的每次迭代耗时相对固定主要时间花在从显存中读取庞大的 KV Cache 进行矩阵乘法的操作上因此总耗时与需要生成的回答长度严格成正比。1.3 一个简单的类比想象你要写一篇论文Prefill就像是你阅读并消化参考文献的过程。你集中时间一次性把所有相关论文读完做好笔记构建 KV Cache并基于所有资料想好了论文的第一句话生成第一个 token。Decode就像是你动手撰写论文正文的过程。你写下一句话后要基于已有的全部内容你的笔记已写出的正文来构思下一句话。这个过程只能一句一句进行无法同时写第二句和第三句。这个根本性的差异导致了它们在性能优化上的思路完全不同。2. 性能特征与瓶颈为什么 Decode 常是速度的“短板”理解了本质我们就能分析它们的性能表现。在实际的模型服务如 vLLM, TGI, TensorRT-LLM中监控指标通常会明确区分Prefill Latency首字延迟和Per-token Latency逐字延迟。特性Prefill 阶段Decode 阶段计算模式计算密集型高度并行内存带宽密集型严格串行主要耗时与提示词长度线性相关每次迭代耗时固定与生成长度线性相关关键瓶颈GPU 的FLOPs浮点运算能力GPU 的内存带宽、KV Cache 读写速度优化重点提高计算效率算子融合FlashAttention优化 KV Cache 内存布局提高带宽利用率PagedAttention对用户体验影响影响首次响应速度影响文本生成流式输出的流畅度Decode 阶段为什么容易成为瓶颈因为对于长文本生成比如生成一篇千字文章Decode 需要执行成百上千次迭代。即使每次迭代只花 50 毫秒生成 100 个 token 也需要 5 秒。而 Prefill 阶段可能只用了几百毫秒。在流式输出场景下用户对“卡顿”的感知主要就来自 Decode 阶段每次迭代的延迟。更关键的是Decode 的瓶颈往往不在 GPU 的计算能力而在内存带宽。每次生成新 token 都需要把整个 KV Cache可能占据数 GB 显存从显存读到计算核心这个数据搬运的速度是有上限的。这就是为什么像vLLM这样的框架其核心创新PagedAttention能极大提升吞吐量——它通过更高效地管理 KV Cache 的内存变相提高了有效带宽的利用率。注意不要用很短的生成任务例如只生成10个token来评估模型的“Decode性能”这无法暴露长文本生成下的真实瓶颈。测试时应模拟真实场景的生成长度。3. 工程实践启示如何根据阶段特性进行优化和选型知道了“为什么”我们就能指导“怎么做”。Prefill 和 Decode 的差异直接影响从提示词工程到服务部署的各个环节。3.1 提示词设计长短与结构的权衡长提示词的成本在 Prefill如果你使用非常长的系统提示词System Prompt或提供了大量上下文RAG 检索结果这会显著增加 Prefill 阶段的耗时。用户会感觉“第一次响应变慢了”。Decode 不关心提示词长度一旦 Prefill 完成后续 Decode 每个 token 的速度与提示词长短基本无关因为 KV Cache 已就绪只是读取。所以对于需要多轮交互、持续生成的对话场景一次性提供充足的上下文可能是值得的。实践建议追求首字速度精简你的提示词特别是系统指令部分。追求整体效率如果一次交互需要模型基于大量上下文进行长文生成那么接受稍长的 Prefill换取后续流畅的 Decode 是合理的。可以考虑将固定系统提示在服务启动时就 Prefill 好某些框架支持。3.2 推理框架与参数配置不同的推理框架对这两个阶段的优化侧重点不同。批处理Batching策略Prefill非常适合批处理因为多个请求的提示词可以矩阵并行计算。Decode的批处理更复杂。由于每个请求的生成进度不同它们的 KV Cache 大小和计算路径也不同这被称为Ragged Batching。vLLM 的 PagedAttention 正是为此而生。KV Cache 量化这是优化 Decode 阶段内存带宽压力的关键手段。将 KV Cache 从 FP16 量化到 INT8 甚至 INT4可以大幅减少数据量提升 Decode 速度但可能会轻微影响生成质量。Prefill 阶段通常使用高精度计算因为它的计算是离线的、一次的对精度要求高。连续批处理Continuous Batching这是现代高性能推理服务器的核心。它动态地将新来的请求Prefill和正在生成的请求Decode的计算任务拼接在一起最大化 GPU 利用率。你需要关注框架是否支持此特性。3.3 服务监控与性能评估评估一个 LLM 服务必须拆开看首字延迟Time to First Token, TTFT主要由 Prefill 阶段决定。影响用户“等待开始”的体验。词间延迟Inter-token Latency即 Per-token Latency由 Decode 阶段决定。影响文本“流出”的流畅度。吞吐量Throughput在连续批处理下单位时间内处理的 token 总数。高吞吐量通常通过增大批处理大小来实现但这可能会牺牲单个请求的延迟。你的应用场景决定了你该关注什么对话机器人TTFT 和 词间延迟 都重要需要平衡。文档摘要/代码生成生成长度较长词间延迟和吞吐量更关键。实时翻译TTFT 极其关键同时需要较低的词间延迟。4. 前沿探索与未来方向打破 Decode 的串行枷锁串行 Decode 是当前 LLM 推理的根本性限制也是研究的热点。除了优化内存带宽人们也在探索更根本的解法推测解码Speculative Decoding用一个更小、更快的“草稿模型”先快速生成一串候选 token然后让大模型“验证模型”并行地对这串候选进行验证和修正。这本质上是在“赌”多个 token 连续生成的概率将部分串行过程转化为并行验证。它不改变模型结构是当前最实用的加速手段之一。Chunked Prefill这是搜索热词中提到的一个思路。对于超长上下文将 Prefill 过程也分块Chunk进行避免单次过大的计算图更好地与 Decode 阶段进行流水线调度提升 GPU 利用率。并行解码模型架构如Medusa框架在模型顶部添加额外的“预测头”使其能同时预测多个未来的 token。这需要修改模型结构或添加轻量级适配。状态空间模型SSM等新架构像 Mamba 这样的模型试图用递归状态替代全局注意力理论上可以实现更高效的序列生成但其在长上下文和语言建模上的综合能力仍在追赶 Transformer。对于大多数开发者和应用者来说当前最切实可行的路径是选择一个优化良好的推理框架如 vLLM合理设计提示词并根据业务需求在延迟和吞吐量之间做出明确的配置选择。理解 Prefill 和 Decode是你从“调用 API 的用户”转向“理解模型服务的构建者”的关键一步。它不再让你面对缓慢的生成速度时束手无策而是能让你有针对性地进行排查是提示词太长导致 Prefill 慢了还是生成任务太重导致 Decode 累积延迟高或者是 KV Cache 太大挤爆了显存下次当你调试 LLM 应用性能时不妨先问自己两个问题我的瓶颈是在构建“记忆宫殿”Prefill还是在“逐字创作”Decode我的优化手段是针对计算还是针对内存带宽想清楚了这些你的优化之路就会清晰得多。
返回列表