Skip to content

调度系统 — 概念

连续批处理(Continuous Batching)

传统静态批处理中,一个 batch 内所有请求必须全部完成才能开始新 batch。Continuous Batching 打破了这个限制:

关键优势:

  • 更低的延迟:新请求无需等待整个 batch 完成
  • 更高的吞吐:GPU 始终保持满载
  • 更公平的调度:短请求不会被长请求阻塞

Chunked Prefill

长 prompt 的 prefill 可能非常耗时(占用大量计算资源和显存)。Chunked Prefill 将 prefill 分成多个 chunk:

好处:

  • 降低 TTFT:不需要一次性处理完整个 prompt
  • 混合调度:prefill 和 decode 可以在同一轮迭代中混合执行
  • 显存友好:每次只需分配部分 prompt 的 KV 缓存

Preemption 策略

当显存不足以容纳所有活跃请求的 KV 缓存时,调度器会触发 preemption:

1. Re-computation(重新计算)

直接丢弃被抢占请求的 KV 缓存块。当请求恢复时,重新计算 prefill。适用于抢占时间短的场景。

2. Swapping(交换到 CPU)

将 KV 缓存块从 GPU 交换到 CPU 内存。恢复时再交换回来。适用于抢占时间较长的场景。

3. 异步抢占多帧丢弃

当使用推测解码或流水线并行时,被抢占请求可能还有多个在途(in-flight)的输出帧。旧的实现使用布尔标志只能丢弃一帧,新的计数器机制逐帧正确排空:

discard_latest_async_tokens (bool) → async_tokens_to_discard (int counter)

调度器将 async_tokens_to_discard 设为 num_output_placeholders,异步调度器每帧递减计数器,确保所有在途帧被正确排空后才恢复请求。

4. KV Connector 延迟释放

KV Connector 的异步操作可能在请求从调度队列移除后仍在进行。has_finished_requests() 现在额外检查 self.requests 中是否还有等待 KV connector 延迟清理的请求,确保调度器不会过早认为"无请求"。

请求队列与优先级

调度器维护多个请求队列:

队列用途
waiting等待 prefill 的新请求
running正在 decode 的活跃请求
swapped被交换到 CPU 的请求

调度优先级:

  1. 处理 swapped 队列(恢复被抢占的请求)
  2. 继续 running 队列的 decode
  3. 从 waiting 队列添加新 prefill

调度决策流程

调度配置参数

参数默认值含义
max_num_seqs256最大并发序列数
max_num_batched_tokens8192每轮迭代最大 token 数
max_model_len模型默认最大序列长度
chunked_prefill_enabledTrue是否启用 chunked prefill
scheduling_policy"fcfs"调度策略(先来先服务/优先级)

相关概念