解耦预填充 (实验性)#
本页介绍 vLLM 中的解耦预填充功能。
注意
此功能为实验性功能,可能会发生更改。
为什么使用解耦预填充?#
两个主要原因
分别调整首 token 延时 (TTFT) 和 token 间延时 (ITL)。解耦预填充将 LLM 推理的预填充和解码阶段置于不同的 vLLM 实例中。这使您可以灵活地分配不同的并行策略(例如
tp
和pp
)来调整 TTFT 而不影响 ITL,或调整 ITL 而不影响 TTFT。控制尾部 ITL。在没有解耦预填充的情况下,vLLM 可能会在一个请求的解码过程中插入一些预填充作业。这会导致更高的尾部延迟。解耦预填充可以帮助您解决此问题并控制尾部 ITL。使用适当的分块大小进行分块预填充也可以实现相同的目标,但实际上很难确定正确的分块大小值。因此,解耦预填充是控制尾部 ITL 更可靠的方法。
注意
解耦预填充不会提高吞吐量。
使用示例#
有关解耦预填充的示例用法,请参阅 examples/online_serving/disaggregated_prefill.sh
。
基准测试#
有关解耦预填充基准测试,请参阅 benchmarks/disagg_benchmarks/
。
开发#
我们通过运行 2 个 vLLM 实例来实现解耦预填充。一个用于预填充(我们称之为预填充实例),一个用于解码(我们称之为解码实例),然后使用连接器将预填充 KV 缓存和结果从预填充实例传输到解码实例。
所有解耦预填充的实现都在 vllm/distributed/kv_transfer
下。
解耦预填充的关键抽象概念
连接器 (Connector):连接器允许 kv 消费者 (kv consumer) 从 kv 生产者 (kv producer) 检索一批请求的 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
一样。