@akshay_pachaar: vLLM 如何避免一个长 prompt 拖慢其他请求:(分块预填充,讲得明明白白)每个 LLM 请求都有两个阶…

X AI KOLs Timeline 工具

摘要

一篇技术解析,介绍 vLLM 的分块预填充(chunked prefill)如何防止长 prompt 阻塞并发的解码请求,涵盖延迟权衡、混合批处理,以及 vLLM V1 中的 `--max-num-batched-tokens` 参数。

vLLM 如何避免一个长 prompt 拖慢其他请求: (分块预填充,讲得明明白白) 每个 LLM 请求都包含两个阶段。 预填充(prefill)阶段并行处理完整的输入 prompt。它计算密集,会构建请求的 KV 缓存,并生成第一个输出 token。 解码(decode)阶段逐个 token 生成剩余的回复。每一步都要反复读取模型权重和 KV 缓存,因此主要受内存带宽限制。 现在假设请求 A 已经在解码并流式输出 token,此时请求 B 带着一个 32K token 的 prompt 到达。 如果没有分块预填充,vLLM 会在一次大块处理中完成 B 的整个 prompt。在此期间请求 A 无法生成下一个 token,因此它的回复看起来像是卡住了。 分块预填充将 B 的 prompt 切分成更小的 token 区间。vLLM 可以先处理一个分块,让活跃请求有机会继续解码,然后在后续的迭代中继续完成 B 的预填充。 prompt 最终还是被完整处理了,只不过不再以一个连续不断的大块占满 GPU。 这就引入了一个重要的延迟权衡。 → 较小的分块能让活跃的回复持续流动。 它们会更频繁地将控制权交还给调度器,从而降低已经在接收回复的用户的 token 间延迟峰值。 → 较大的分块能让新请求更快启动。 在处理完所有 prompt 分块之前,B 无法生成第一个 token。较大的分块用更少、更高效的轮次完成这项工作,通常能改善首 token 延迟(time to first token)。 → 分块过小会带来额外开销。 后续的分块必须对前面分块生成的 token 状态进行注意力计算。过度切分会反复读取更多 KV 缓存,可能降低 GPU 利用率。 → 混合批处理能更充分地利用 GPU。 预填充是计算密集型,而解码是内存密集型。将预填充分块与活跃的解码任务一起调度,可以让两类工作更高效地共享同一次迭代。 不存在一个通用的最佳分块大小。 长 prompt、大量并发请求以及严格的流式输出目标通常更适合较小的分块;而优先考虑首 token 延迟的工作负载则可能受益于较大的分块。 在 vLLM V1 中,`--max-num-batched-tokens` 控制一次迭代中可以调度多少 token。它是管理这一权衡的主要设置之一。 分块预填充并不会减少长 prompt 产生的工作量,它只是防止这项工作去决定其他人何时收到下一个 token。 如果你想深入了解这个话题,我写了一篇关于 LLM 中批处理策略的完整解析文章。 原文如下引用。
查看原文
查看缓存全文

缓存时间: 2026/10/05 19:37

vLLM 是如何防止一个长 prompt 卡住其他请求的:

(分块预填充(chunked prefill),一次讲清楚)

每个 LLM 请求都包含两个阶段。

Prefill(预填充) 会并行处理完整的输入 prompt。这个阶段计算量很大,会构建请求的 KV cache,并生成第一个输出 token。

Decode(解码) 则逐个生成后续的响应 token。每一步都要反复读取模型权重和 KV cache,因此主要受限于内存带宽。

现在想象一下:请求 A 正在解码并流式输出 token,此时请求 B 携带一个 32K token 的 prompt 到达。

如果没有分块预填充,vLLM 会在一次大块计算中处理完 B 的整个 prompt。在这段时间内,请求 A 无法生成下一个 token,因此它的响应看起来像卡住了。

分块预填充 把 B 的 prompt 拆分成更小的 token 区间。vLLM 可以先处理一个分块,让活跃的请求有机会进行一次解码,然后在后续迭代中继续处理 B 的预填充。

该 prompt 依然会被完整处理,只是不再以一整块的方式独占 GPU。

这就引出了一个重要的延迟权衡。

→ 较小的分块能让活跃的响应持续流动。

它们会更频繁地把控制权交还给调度器,减少对那些已经在接收答案的用户来说的 token 间延迟抖动。

→ 较大的分块能帮助新请求更快启动。

在处理完所有 prompt 分块之前,B 无法生成第一个 token。更大的分块可以用更少、更高效的批次完成这部分工作,通常会改善首 token 延迟(time to first token)。

→ 分块过小会带来额外开销。

后面的分块必须对前面分块产生的 token 状态执行 attention。过度拆分会反复读取更多的 KV cache,可能降低 GPU 利用率。

→ 混合批次可以更充分地利用 GPU。

预填充属于计算密集型,而解码属于内存密集型。将预填充分块与活跃的解码调度在一起,可以让这两类工作在同一次迭代中更高效地共享资源。

不存在通用的最优分块大小。

长 prompt、大量并发请求以及严格的流式输出要求,通常更偏向较小的分块。而那些优先追求首 token 延迟的工作负载,使用较大的分块可能更有优势。

在 vLLM V1 中,--max-num-batched-tokens 控制一次迭代中可以调度多少个 token,它是调节这一权衡的主要配置项之一。

分块预填充并不会减少长 prompt 本身产生的计算工作量。它只是阻止这部分工作去决定其他所有人何时能收到下一个 token。

如果你想了解更多相关内容,我写了关于 LLM 中批处理策略的完整解析。

文章全文摘录如下。

相似文章