Chunked Prefill 解决了什么问题?它如何平衡 TTFT、TPOT 和吞吐量?
简化版
Chunked Prefill(分块预填充) 把长 prompt 的 Prefill 切成多个 token 块,让调度器能在块之间插入其他请求的 Decode,避免一次超长 Prefill 长时间霸占 GPU、把正在生成的请求「卡住」(队头阻塞)。较小的块更照顾 TPOT 和输出流畅度,较大的块让单个 prompt 的 prefill 更快完成。它改变的是调度粒度,并不减少总的 prefill 计算量。
详细版
Prefill 通常算力受限、Decode 通常访存受限。把长 prefill 切块后,调度器可以在同一轮的 token 预算里,先安排一批 Decode token,再用剩余预算处理一部分 prefill——既保护正在生成的请求不被长 prefill 饿死,又让计算密集的 prefill 和访存密集的 decode 混在一起、更充分利用 GPU。
代价:一个新的长请求可能要经过多轮才能填完 prompt,TTFT 受块大小和 Decode 优先级影响;切得太细还增加调度和 kernel 启动开销。参数必须按输入长度、活跃 Decode 数、硬件、SLA 压测确定,不能照搬固定值。
完整版教学
一、队头阻塞怎么产生:一个时间线
不切块时,若调度器一次性处理一个 10 万 token 的超长 prompt,会发生什么?
不切块(长 prefill 独占 GPU):
已有会话的 Decode: ████ ──────【被10万token的prefill卡住,几百ms没动】────── ████
P99 的 ITL(token间隔)在这段时间突刺,用户感觉"卡住不动了"
GPU 在处理这个巨型 prefill 的几百毫秒里,无法为已有会话生成下一个 token,导致这些会话的 TPOT 和 P99 ITL 突然飙升——用户体验就是「打字打到一半卡住」。反过来,若完全优先 Decode、让新长 prompt 一直等,则新请求的 TTFT 会长到无法接受。两头都不好,这就是要 Chunked Prefill 的原因。
二、切块后怎么调度:token 预算
调度器维护每轮最大 token 预算(如 2048 token/轮)。切块后,每轮这样分配:
每轮 token 预算 = 2048
先放:正在生成的 N 个 Decode token(保证已有会话流畅,如 N=200)
再放:某长 prompt 的下一个 prefill 块(用剩余 1848 预算)
→ 长 prompt 被分成多轮逐块 prefill,同时 Decode 从不中断
长 prompt 的所有块处理完后,该请求才进入正常 Decode。实现上可选 Decode 优先、Prefill 优先、或基于截止时间的混合策略——并非所有 Chunked Prefill 都用同一优先级。
记忆钩子:Chunked Prefill = 把长时间占用 GPU 的”读题”过程切成小段,让正在”答题”的请求穿插着继续输出——用调度粒度换流畅度。
三、块大小的影响:一个权衡旋钮
块大小是核心调参,两个方向拉扯:
| 块大小 | TPOT/流畅度 | 长 prompt 的 TTFT | 效率/开销 |
|---|---|---|---|
| 小块 | 好(频繁回到 Decode,ITL 平稳) | 差(要更多轮才填完) | 差(轮数多、kernel 启动开销大) |
| 大块 | 差(长 prefill 仍会阻塞 Decode) | 好(更快填完) | 好(大矩阵效率高) |
小块让调度器更频繁回到 Decode、降低长 prefill 对 ITL 的干扰,但增加轮数和固定开销;大块提高 prefill 矩阵效率、改善该请求 TTFT,但更易阻塞 Decode。块大小还受 KV Cache 容量、最大批 token、算子形状约束。
四、为什么能提高利用率
Prefill(算力受限)和 Decode(访存受限)的资源特征互补。把两者合理放进同一调度轮,理论上能让 GPU 的算力单元和显存带宽同时被利用——prefill 吃算力时,decode 吃带宽,互不完全冲突。但是否真更快取决于推理引擎的 kernel 实现,混合 batch 的实际收益要实测,不能只凭理论断言。
五、和其他方案的关系(别搞混)
三个容易混淆的调度概念,边界要清楚:
- Continuous Batching:决定请求可以动态进出 batch(迭代级调度)。
- Chunked Prefill:在此基础上,进一步允许单个长 prompt 分多轮进入。
- Prefill/Decode 分离部署:把两阶段放到不同的资源池/实例,需要在它们之间传输 KV Cache——这和”切块”是两回事,不要混为一谈。
三者常配合使用,但解决的问题不同。
六、评估方法
Chunked Prefill 解决的是在线混合流量下的相互干扰,所以:
- 必须用长短 prompt 混合的流量测试,测 P50/P99 的 TTFT、TPOT、prefill 完成时间、总吞吐、调度抢占次数;
- 只测单个长请求看不到它的价值——它的意义在于「长请求不干扰短请求的生成」,单请求场景根本没有这种干扰。
七、加强记忆
Chunked Prefill 记「切长 prefill、穿插 decode、防队头阻塞」:把长 prompt 的 prefill 切成 token 块,调度器每轮先保 Decode、再用剩余预算填一块 prefill,避免超长 prefill 霸占 GPU 卡住正在生成的请求。核心权衡——块小则流畅(护 TPOT)但轮多开销大且长 prompt 的 TTFT 变差;块大则 prefill 快但易阻塞 Decode,由 SLA 定夺。它只改调度粒度、不减总计算量,要和 Continuous Batching(动态进出)、Prefill/Decode 分离(跨资源池传 KV)区分开,且必须用长短混合流量评估。