分离式预填充(实验性)¶
本页面将介绍 vLLM 中的分离式预填充功能。
注意
此功能为实验性功能,可能会有所更改。
为何使用分离式预填充?¶
两个主要原因
- 独立调整首词时间 (TTFT) 和词间延迟 (ITL)。分离式预填充将 LLM 推理的预填充阶段和解码阶段置于不同的 vLLM 实例中。这使您能够灵活地为不同的并行策略(例如
tp
和pp
)分配,以在不影响 ITL 的情况下调整 TTFT,或在不影响 TTFT 的情况下调整 ITL。 - 控制尾部 ITL。在没有分离式预填充的情况下,vLLM 可能会在请求解码期间插入一些预填充任务。这会导致更高的尾部延迟。分离式预填充有助于您解决此问题并控制尾部 ITL。使用适当分块大小的分块预填充也可以实现相同的目标,但在实践中很难确定正确的块大小值。因此,分离式预填充是控制尾部 ITL 的更可靠方法。
注意
分离式预填充并不能提高吞吐量。
使用示例¶
请参考 examples/online_serving/disaggregated_prefill.sh 以获取分离式预填充的使用示例。
性能基准¶
请参考 benchmarks/disagg_benchmarks 以获取分离式预填充的性能基准。
开发¶
我们通过运行 2 个 vLLM 实例来实现分离式预填充。一个用于预填充(我们称之为预填充实例),另一个用于解码(我们称之为解码实例),然后使用连接器将预填充的 KV 缓存和结果从预填充实例传输到解码实例。
所有分离式预填充的实现都在 vllm/distributed/kv_transfer
目录下。
分离式预填充的关键抽象
- 连接器:连接器允许 KV 消费者 从 KV 生产者 检索一批请求的 KV 缓存。
- 查找缓冲区:查找缓冲区提供两个 API:
insert
KV 缓存和drop_select
KV 缓存。insert
和drop_select
的语义类似于 SQL,其中insert
将 KV 缓存插入到缓冲区中,drop_select
则返回与给定条件匹配的 KV 缓存并将其从缓冲区中删除。 - 管道:一个用于张量传输的单向 FIFO 管道。它支持
send_tensor
和recv_tensor
。
注意
insert
是非阻塞操作,而 drop_select
是阻塞操作。
下图展示了上述 3 种抽象的组织方式
分离式预填充的工作流程如下
buffer
对应于 LookupBuffer 中的 insert
API,而 drop_select
对应于 LookupBuffer 中的 drop_select
API。
第三方贡献¶
分离式预填充与基础设施高度相关,因此 vLLM 依赖第三方连接器来实现生产级别的分离式预填充(vLLM 团队将积极审查并合并用于第三方连接器的新 PR)。
我们推荐以下三种实现方式
- 完全定制的连接器:实现您自己的
Connector
,并调用第三方库来发送和接收 KV 缓存,以及更多功能(例如修改 vLLM 的模型输入以执行定制的预填充等)。这种方法提供了最大的控制权,但存在与未来 vLLM 版本不兼容的风险。 - 数据库式连接器:实现您自己的
LookupBuffer
,并像 SQL 一样支持insert
和drop_select
API。 - 分布式 P2P 连接器:实现您自己的
Pipe
,并像torch.distributed
一样支持send_tensor
和recv_tensor
API。