分离式预填充(实验性)#
本页介绍 vLLM 中的分离式预填充特性。
注意
此功能为实验性功能,可能会发生更改。
为什么使用分离式预填充?#
两个主要原因
分别调整首 token 延迟 (TTFT) 和 token 间延迟 (ITL)。 分离式预填充将 LLM 推理的预填充和解码阶段置于不同的 vLLM 实例中。 这使您可以灵活地分配不同的并行策略(例如
tp
和pp
)来调整 TTFT 而不影响 ITL,或调整 ITL 而不影响 TTFT。控制尾部 ITL。 在没有分离式预填充的情况下,vLLM 可能会在一个请求的解码过程中插入一些预填充作业。 这会导致更高的尾部延迟。 分离式预填充可以帮助您解决此问题并控制尾部 ITL。 使用适当 chunk 大小的分块预填充也可以达到相同的目的,但实际上很难确定正确的 chunk 大小值。 因此,分离式预填充是控制尾部 ITL 的更可靠方法。
注意
分离式预填充 不会 提高吞吐量。
使用示例#
请参考 examples/online_serving/disaggregated_prefill.sh
以获取分离式预填充的使用示例。
基准测试#
请参考 benchmarks/disagg_benchmarks/
以获取分离式预填充的基准测试。
开发#
我们通过运行 2 个 vLLM 实例来实现分离式预填充。 一个用于预填充(我们称之为预填充实例),另一个用于解码(我们称之为解码实例),然后使用连接器将预填充 KV 缓存和结果从预填充实例传输到解码实例。
所有分离式预填充的实现都在 vllm/distributed/kv_transfer
下。
分离式预填充的关键抽象
连接器 (Connector):连接器允许 KV 消费者 从 KV 生产者 检索一批请求的 KV 缓存。
查找缓冲区 (LookupBuffer):LookupBuffer 提供两个 API:
insert
KV 缓存 和drop_select
KV 缓存。insert
和drop_select
的语义类似于 SQL,其中insert
将 KV 缓存插入缓冲区,而drop_select
返回与给定条件匹配的 KV 缓存并将其从缓冲区中删除。管道 (Pipe):用于张量传输的单向 FIFO 管道。 它支持
send_tensor
和recv_tensor
。
注意
insert
是非阻塞操作,但 drop_select
是阻塞操作。
下图说明了以上 3 个抽象是如何组织的

分离式预填充的工作流程如下

buffer
对应于 LookupBuffer 中的 insert
API,而 drop_select
对应于 LookupBuffer 中的 drop_select
API。
第三方贡献#
分离式预填充与基础设施高度相关,因此 vLLM 依赖于第三方连接器来实现生产级别的分离式预填充(并且 vLLM 团队将积极审查和合并用于第三方连接器的新 PR)。
我们推荐三种实现方式
完全自定义连接器 (Fully-customized connector):实现您自己的
Connector
,并调用第三方库来发送和接收 KV 缓存,以及更多功能(例如编辑 vLLM 的模型输入以执行自定义预填充等)。 这种方法为您提供了最大的控制权,但也存在与未来 vLLM 版本不兼容的风险。类数据库连接器 (Database-like connector):实现您自己的
LookupBuffer
并支持insert
和drop_select
API,就像 SQL 一样。分布式 P2P 连接器 (Distributed P2P connector):实现您自己的
Pipe
并支持send_tensor
和recv_tensor
API,就像torch.distributed
一样。