Serving

Serving

一分为二:面向 SLO 的 LLM 预填充/解码分离架构

一分为二:面向 SLO 的 LLM 预填充/解码分离架构 单个服务实例把提示词处理与逐词元生成混在一起,实现起来很简单,对很多部署来说也是正确选择。但一旦你需要在持续请求速率下满足延迟目标,LLM 请求的两个阶段就会在同一批 GPU 上互相干扰。预填充/解码分离(prefill/decode disaggregation)通过把两个阶段拆分到独立的机器池、并用快速的 KV 缓存交接把它们连接起来,消除了这种冲突。本文基于主要的系统论文(DistServe、Splitwise、Mooncake)以及生产引擎(vLLM、NVIDIA Dynamo)的现行官方文档,说明分离架构到底买到了什么——以及买不到什么。 文中所有性能数字均引自所列论文与官方文档,并附有各自的测试环境;本文未在本机复现任何一项。文章最后给出一个可在单机上执行的确定性轨迹回放实验设计,用来实测这一权衡。 两种延迟,一条队列 一个 LLM 请求包含资源画像截然相反的两个阶段: 预填充(prefill):用一次前向传播处理完整提示词并产出第一个词元。它受计算限制:对 13B 模型而言,512 个词元的提示词已足以让一块 A100 接近计算饱和 [1]。 解码(decoding):逐词元、逐步生成后续输出。每一步都要读取整个 KV 缓存,因此受显存带宽限制,计算单元大量空闲 [1, 2]。 两个延迟指标由此而来。首词元时间(time to first token,TTFT)主要由预填充阶段决定;每输出词元时间(time per output token,TPOT)是解码阶段的平均单步时间。vLLM 官方文档把 TPOT 称为 inter-token latency(ITL),并将 TTFT 与 ITL 视为两个可独立调优的在线服务目标 [4]。 问题在于:在共置(单体)实例中,两个阶段共享同一块 GPU 和同一条队列。连续批处理(continuous batching)刻意把两者混批,于是一次漫长的预填充会拉长与其同批的解码步骤(TPOT 恶化),而同批的解码工作也会推迟预填充(TTFT 恶化)。DistServe 在 13B 模型上的测量清楚地展示了这一效应:在单块 A100 上以 90% SLO 达成率为目标,单体系统大约只能支撑 1.6 请求/秒,而同一块 GPU 若只做预填充可支撑 5.6 请求/秒,只做解码可支撑 10 请求/秒。用 2 块 GPU 做预填充、1 块做解码,即可服务 10 rps——即每 GPU 3.3 rps,是单体系统的 2.1 倍 [1]。

字体
阴影
滤镜
圆角
主题色