pp8并行,update_from_output 会等所有rank的 model_executor.execute_model 执行完了之后才会执行吗
是的,pp=8(pipeline parallel 8)时,update_from_output 会等所有 rank 的 model_executor.execute_model 执行完毕后才会执行。因为 update_from_output 需要依赖所有 pipeline stage 的输出结果来更新调度器状态,这一流程在 vLLM 的调度器接口文档和源码中有明确体现,必须等模型推理阶段全部完成后统一更新状态,保证数据一致性。
详见 SchedulerInterface.update_from_output 和 Scheduler.update_from_output。
需要更详细的执行流程说明吗?
Sources:
Hint: Mention @RunLLM in the post for followups.
@RunLLM 如果是pd分离场景,p是pp8,那也会等kvcache传输完之后,才会走到 update_from_output 里了?因为 kvcache传输完之后,model_executor.execute_model 才会执行完的把
是的,在PD分离场景下,如果P端是pp=8,update_from_output同样会等KVCache传输完成后才会执行。因为model_executor.execute_model只有在KVCache传输完成后,所有pipeline stage的推理才算结束,调度器才能安全地调用update_from_output进行状态更新。这一机制在相关PR和设计文档中有明确说明,确保数据一致性和正确性。参考、设计说明
需要详细解释KVCache传输与pipeline并行的具体同步流程吗?
Sources:
- https://github.com/vllm-project/vllm/pull/19558
- https://docs.vllm.ai/en/latest/design/p2p_nccl_connector/
Hint: Mention @RunLLM in the post for followups.
@RunLLM 那这样不是比较慢吗 只有等模型执行完了之后,才会执行下一轮的调度?
是的,这样确实会带来一定的延迟,因为必须等所有pipeline stage的模型推理和KVCache传输全部完成后,才能进入下一轮调度。这样会导致调度粒度较粗,无法做到完全流水线式的异步调度。相关讨论指出,当前vLLM的同步调度机制会在每轮等待所有执行完成后再调度下一批请求。
需要更详细的性能分析或优化方向说明吗?
Sources:
Hint: Mention @RunLLM in the post for followups.
@RunLLM 非PP并行普通场景下,也是这样吗
不是。在非PP(pipeline parallel)并行的普通场景下,调度器通常只需等待单次模型推理(即所有TP分片或单卡)完成即可进入下一轮调度,无需像PP那样等待多stage串行完成。官方文档明确说明,TP(tensor parallel)下各分片是同步执行的,调度粒度更细,延迟更低。
需要详细对比TP和PP下调度流程的区别吗?
Sources:
Hint: Mention @RunLLM in the post for followups.
@RunLLM update_from_output 同步等待模型执行完的地方的代码在哪里
在vLLM中,update_from_output同步等待模型执行完成的代码位置在调度器接口的实现里。具体来说,SchedulerInterface.update_from_output方法会在模型执行(model_executor.execute_model)全部完成后被调用,用于更新调度状态。其实现可见于vllm/v1/core/sched/interface.py和官方API文档。
需要详细源码调用链说明吗?
Sources:
Hint: Mention @RunLLM in the post for followups.
@RunLLM 但是PP并行的时候不是走的 step_with_batch_queue 吗,如果是PD分离场景,running队列里有两个(r1, r2),其中一个r1执行完了,走到 update_from_output 里,但这个时候 r2 可能刚传输完kvcache ,还没走到 update_from_output 里,但这个时候在r1 在 update_from_output 流程里遍历所有running队列,释放 _free_blocks, 会检查到r2的请求状态还未结束(是在update_from_output 设置的),就会报 assert request.is_finished() 的断言错误吧
你的理解是正确的,这正是vLLM在PD分离+PP场景下曾经遇到的典型race condition问题:
当PP并行时,确实是走的step_with_batch_queue,而不是普通的step。此时如果有多个request(如r1、r2)在running队列,r1先完成并进入update_from_output,但r2的KVCache还未传输完、未完成,遍历running队列时会发现r2未结束,调用_free_blocks(request)时就会触发assert request.is_finished()断言失败,报错。
这个问题在vLLM社区有详细讨论和修复,相关PR和issue都明确指出了race的根源和修复方式:需要确保只有在request真正完成后才释放blocks,避免提前free导致断言失败。
需要详细race condition复现流程或修复方案说明吗?
Sources:
Hint: Mention @RunLLM in the post for followups.
@RunLLM 那修复方案是怎么样的,该场景是不是只有在PP并行的时候出现?
修复方案是在update_from_output和_free_blocks等释放KV cache的逻辑中,增加对request状态的检查,只有当request真正完成(is_finished)时才释放blocks。对于race condition,建议在释放前加判断,避免未完成的request被提前free,防止assert失败。相关PR已实现此修复。
该场景主要在PP(pipeline parallel)并行时出现,尤其是PD分离+PP下多request并发时更容易复现。普通非PP场景一般不会遇到此问题。PR讨论有详细说明。
需要更详细的代码片段或race condition分析吗?
Sources:
Hint: Mention @RunLLM in the post for followups.
@RunLLM 但是如果这样修改,不是会造成kvcache 泄露了吗,不会释放了,因为已经发送了 finished_sending 消息
你的担心有道理。如果仅仅在is_finished()时才释放KV cache,确实可能导致KV cache未及时释放,出现内存泄漏,尤其是在已经发送了finished_sending消息但未释放blocks的情况下。
相关PR讨论中也提到,正确做法是结合异步通知机制:只有在确认所有异步发送/接收(如KVCache传输)完成后,才安全释放blocks,避免提前free或泄漏。
需要详细说明如何结合异步通知和状态机安全释放KV cache吗?
Sources:
Hint: Mention @RunLLM in the post for followups.
@RunLLM 请问下 unscheduled_req_ids ,什么情况下会出现
unscheduled_req_ids 会在以下两种情况下出现:
- 某些请求(request)在本轮调度中未被分配到执行(即未被调度),比如被抢占、预调度失败或资源不足时;2. 这些请求可能是被抢占的(preempted)请求,或是上轮正在运行但本轮未被选中的请求。此时它们会从持久化batch中移除,但其缓存状态会保留,以便后续重新调度。详见源码说明 和 官方API文档。
需要详细举例说明吗?
Sources:
- https://github.com/vllm-project/vllm/blob/main/vllm/v1/worker/gpu_model_runner.py
- https://docs.vllm.ai/en/latest/api/vllm/v1/worker/gpu_model_runner/#vllm.v1.worker.gpu_model_runner.GPUModelRunner._update_states
Hint: Mention @RunLLM in the post for followups.
@RunLLM 持久化batch中包含的是哪些请求?