跳转至

五十五:Sarathi-Chunked Prefill

来源:http://mp.weixin.qq.com/s?__biz=MzYyNTk3Njg1NA==&mid=2247484710&idx=1&sn=b7090b17bfd8164c8fae50a9d8bba02e&chksm=f01eb65fc7693f4996f7354d0d3bdababa39885f8cca0c61b192291a18d886b09422016e3626#rd

1. 学习范围

本日主题是 Sarathi,重点是 chunked prefill、prefill 和 decode 的协同调度,以及如何减少 decode stall。

img

本日覆盖: - Sarathi 的定位和问题定义。

  • 为什么长 Prefill 会阻塞 Decode。

  • Chunked prefill 的核心思想。

  • Piggyback decoding 的含义。

  • Stall-free schedule 的目标。

  • Chunk size、batch 形态和调度权衡。

  • 与 DistServe、vLLM 的区别。

  • 常见面试问题和生产化注意事项。

2. Sarathi 的定位

Sarathi 是一种 LLM 推理调度方案,核心目标是让长 prompt 的 Prefill 不再长时间独占 GPU,从而减少 Decode 等待和输出卡顿。

img

它的基本思路不是把 Prefill 和 Decode 完全分离,而是: - 把长 Prefill 切成多个 chunk。

  • 在 chunk 之间穿插 Decode。

  • 让每轮执行的 batch 更均衡。

  • 尽量减少 Decode stall。

Sarathi 关注的是单个 serving 引擎内部的调度效率和 latency-throughput 平衡。

3. 为什么长 Prefill 会阻塞 Decode

如果一个请求有很长的 prompt,传统做法可能一次性把整个 Prefill 放进一个大 batch 执行。 问题是: - Prefill 可能持续很长时间。

  • Decode 请求在 batch 边界之外只能等待。

  • 流式输出会出现停顿。

  • TTFT 和 TPOT 都可能恶化。

对于在线聊天、RAG 和长文档总结,这种阻塞尤其明显。

4. Sarathi 的核心思想

Sarathi 的核心是 chunked prefill:把长 prompt 的 Prefill 切成若干 chunk,每次只处理一部分 token,然后让 Decode 请求 piggyback 在这些 chunk 上一起执行。 可以理解为:

prefill chunk 1 + some decode tokens
prefill chunk 2 + some decode tokens
prefill chunk 3 + some decode tokens
这样做的目标是让每轮调度都兼顾 Prefill 和 Decode,而不是让 Prefill 独占整轮 GPU 时间。

5. Piggyback decoding

Piggyback decoding 指 Decode token 不单独开一轮,而是“搭载”在 Prefill chunk 的执行批次中一起跑。 它利用的事实是: - 大 chunk Prefill 已经占用了主要计算路径。

  • 少量 Decode token 加进去的边际成本相对较小。

  • 一次批次里兼顾两类 token,可减少空泡和切换开销。

因此,Piggyback decoding 的重点不是把 Decode 变成更快的单独任务,而是把它藏进更高效的混合批次中。

6. Stall-free schedule

Sarathi 希望构造一种尽量 stall-free 的 schedule,也就是让 Decode 不因长 Prefill 长时间停摆。 所谓 stall-free,并不是没有等待,而是尽量避免: - decode 阶段被长时间完全阻塞。

  • GPU 有效算力被低效空转。

  • batch 形态剧烈震荡。

理想情况下,每一轮都可以持续推进 Prefill 和 Decode。

7. Chunked prefill 的工作方式

Chunked prefill 会把一个长 prompt 分成多个连续块。 执行时: - 先处理前一个 chunk。

  • 把已完成的中间状态写回 KV cache。

  • 再处理下一个 chunk。

  • 在 chunk 之间插入活跃请求的 Decode token。

这要求系统正确维护位置编码、注意力掩码和 KV 状态,但不会改变模型结果本身。

8. Chunk size

Chunk size 是 Sarathi 的关键参数。 影响包括: - 太大时,仍然会长时间阻塞 Decode。

  • 太小时,chunk 切换频繁,调度和 kernel 开销变大。

  • 不同 chunk size 会影响吞吐、TTFT 和 TPOT。

  • 最优值与模型、硬件和请求分布有关。

chunk size 本质上是在“Prefill 连续性”和“Decode 及时性”之间做平衡。

9. 为什么 chunking 不是简单分片

Chunked prefill 不是把 prompt 随便切断。 它必须保证: - attention 依然能看到正确的历史上下文。

  • KV cache 按顺序增长。

  • 位置编码一致。

  • 中间 chunk 的计算结果可被后续 chunk 继续使用。

所以它是带状态的、严格正确的分段执行,而不是 token 级乱序处理。

10. Sarathi 的调度目标

Sarathi 的调度目标通常包括: - 降低 Decode stall。

  • 保持较高 GPU 利用率。

  • 提升整体吞吐。

  • 控制 TTFT。

  • 控制 P95/P99 延迟。

它不追求单一指标极致,而是找一个更平衡的批次形态。

11. Prefill 和 Decode 的共存

Sarathi 和 DistServe 的思路不同。 Sarathi 的思路是: - Prefill 和 Decode 仍然在同一个执行引擎内共存。

  • 通过 chunking 和 piggybacking 让二者更好地穿插。

DistServe 则更偏向: - 把 Prefill 和 Decode 分离到不同资源池。

因此 Sarathi 是“同池协同调度”,DistServe 是“跨池解耦调度”。

12. 为什么混合批次更高效

单独跑 Decode 时 batch 往往较小,GPU 可能无法充分利用。 如果把 Prefill chunk 和 Decode 合在一起: - batch 更大。

  • kernel 启动次数更少。

  • 计算更连续。

  • Prefill 的大矩阵乘法能够填满 GPU。

但前提是 Decode 不会被过度饿死,所以 chunk size 很关键。

13. 与 continuous batching 的关系

Sarathi 可以看作 continuous batching 的一个强化版本,重点是把长 Prefill 拆分并与 Decode 混合。 区别在于: - continuous batching 关注每个 step 动态增删请求。

  • Sarathi 进一步关注长 Prefill 如何不拖死 Decode。

因此它更强调“调度结构的形状”。

14. 主要收益

Sarathi 可能带来的收益: - 减少 decode stall。

  • 改善流式输出稳定性。

  • 降低大 prompt 对小请求的干扰。

  • 在保持较高吞吐的同时改善延迟分布。

  • 更适合混合负载。

这些收益来自调度形态改变,而不是模型结构改变。

15. 主要代价

代价包括: - 调度逻辑更复杂。

  • chunk size 需要调优。

  • 状态管理更复杂。

  • Prefill 被切块后可能增加调度开销。

  • 如果负载不匹配,收益有限。

chunking 不是免费午餐,它把“长阻塞”换成“更复杂的混合调度”。

16. 对 TTFT 的影响

Chunked prefill 对 TTFT 的影响要分情况看。 可能改善: - 让 Decode 更快开始。

  • 避免长 Prefill 独占 GPU。

也可能恶化: - 如果 chunk 太小或调度策略不佳,Prefill 总完成时间拉长。

  • 首 token 相关路径可能变复杂。

因此不能只看局部;要看端到端 SLO。

17. 对 TPOT/ITL 的影响

Sarathi 的目标之一是让每个 decode token 的输出间隔更稳定。 它可能: - 减少长 Prefill 导致的 Decode 停顿。

  • 改善 token 生成的连贯性。

  • 让流式响应更平滑。

但如果 chunk 太大或 batch 太拥挤,Decode 仍可能受到影响。

18. 适用场景

Sarathi 更适合: - 长 prompt 与短 prompt 混合的在线服务。

  • 需要流式输出的应用。

  • 不想拆成独立 Prefill/Decode 集群的单引擎部署。

  • 希望在同一个 GPU 池内优化调度的场景。

它尤其适合“长输入会拖慢所有人的服务”这种问题。

19. 与 vLLM 的关系

vLLM 解决的是 KV cache 管理和 continuous batching 等问题。Sarathi 则进一步关注如何通过 chunked prefill 和 piggyback decoding 改善混合批次调度。 两者可以看作关注层次不同: - vLLM 更偏推理服务框架与内存管理。

  • Sarathi 更偏调度策略。

20. 与 DistServe 的关系

DistServe 通过物理分离 Prefill 和 Decode 来减少干扰。 Sarathi 则不分离,而是在同一个引擎里把长 Prefill 切块并和 Decode 交错执行。 所以: - DistServe 是架构级解耦。

  • Sarathi 是调度级协同。

它们解决的都是 Prefill/Decode 干扰问题,只是路径不同。

21. 常见失败模式

常见失败包括: - chunk size 过大,Decode 仍然卡顿。

  • chunk size 过小,调度开销和 kernel 开销太高。

  • 只看平均吞吐,忽略 P99。

  • 长输出请求占据过多 decode slots。

  • 负载变化后原先最优 chunk size 不再合适。

所以 Sarathi 需要压测驱动调优。

22. 评估方法

评估 Sarathi 时应关注: - tokens/s。

  • TTFT。

  • TPOT/ITL。

  • P95/P99 latency。

  • Decode stall 时间。

  • GPU 利用率。

  • 不同 chunk size 下的曲线。

最好在长 prompt 占比不同的负载上分别测试。

23. 面试表达要点

面试中回答 Sarathi,建议先讲问题: - 长 Prefill 会阻塞 Decode。

  • 在线流式服务不能接受长时间停顿。

再讲方法: - 把 Prefill 切成 chunk。

  • 在 chunk 间 piggyback Decode。

  • 让混合批次更均衡。

最后讲权衡: - 好处是减少 stall、提升延迟体验。

  • 代价是调度更复杂、chunk size 需要调优。

24. 核心总结

Sarathi 的核心不是把 Prefill 和 Decode 分开,而是让它们在同一个执行引擎内更聪明地混跑。通过 chunked prefill 和 piggyback decoding,它减少了长 prompt 对 Decode 的阻塞,改善了流式输出的稳定性,并在吞吐和延迟之间找到更好的平衡。

25. 参考资料

  • SARATHI: Efficient LLM Inference by Piggybacking Decodes with Chunked Prefills: https://arxiv.org/abs/2308.16369

  • Sarathi-Serve GitHub: https://github.com/microsoft/sarathi-serve

  • DistServe: Disaggregating Prefill and Decoding for Goodput-optimized Large Language Model Serving: https://arxiv.org/abs/2401.09670

  • vLLM documentation: https://docs.vllm.ai/

            预览时标签不可点
    

    <div class="