Prhub

#7141 [BugFix] prevent requests from entering running state without a slot

PaddlePaddle/FastDeploy · 作者 liyonghua0910 · 合并时间 2026-04-03 14:07

分析状态 已生成
文件变更 2提交数 3 · 评论 2
代码增减 +8 / -3
bugfix Scheduler Optimization

执行摘要

修复调度器在请求状态转换时槽位计数不一致的 bug,防止请求无槽位进入运行状态。

根据PR body描述,修复调度器槽位计数不一致的问题。当请求处于运行、待中止、待重新调度或已抢占回等待队列等状态时,调度器可能过度接纳请求,即使有效占用槽位已达到max_num_seqs,仍将新请求移入running状态。这会导致调度器在接近最大并发数时出现状态不一致。

该PR值得精读,特别是对于负责调度器模块的工程师。重点关注resource_manager_v1.py中新的槽位计数逻辑设计,这是调度器正确性的关键保障。建议结合近期调度器相关的PR(如#7152、#7129)一起阅读,理解调度器状态的完整演进。

讨论亮点

Review评论中未提供具体讨论内容。从提交历史看,作者通过三次提交逐步完善了修复:第一次提交添加了基本防护逻辑;第二次提交增加了对to_be_aborted_req_id_set的计数;第三次提交增加了对waiting队列中PREEMPTED状态请求的计数。这表明实现过程中考虑了不同状态请求对槽位占用的影响。

实现拆解

修改集中在两个核心调度文件:

  1. fastdeploy/engine/sched/resource_manager_v1.py:在_allocate_decode_and_extend函数中,将槽位检查条件从仅检查running队列长度,扩展为同时统计running队列、待重新调度请求集合(to_be_rescheduled_request_id_set)、待中止请求集合(to_be_aborted_req_id_set)以及等待队列中状态为PREEMPTED的请求数量。只有当这些总数小于max_num_seqs时,才允许新请求从waiting进入running。
  2. fastdeploy/engine/common_engine.py:在_fetch_request函数中,移除对RuntimeError("cannot schedule new futures after shutdown")的静默处理,改为直接重新抛出异常,确保调度器关闭时的错误能被显式暴露。
文件 模块 状态 重要度
fastdeploy/engine/sched/resource_manager_v1.py Scheduler modified 9.0
fastdeploy/engine/common_engine.py Engine modified 4.0

分析完成后,这里会展示 LLM 生成的相对完整源码片段和详细注释。

关键符号

_allocate_decode_and_extend _fetch_request

评论区精华

调度器槽位计数逻辑的完整性 正确性

从提交历史看,作者通过三次提交逐步完善了槽位计数:第一次仅考虑 running 队列;第二次增加 to_be_aborted_req_id_set;第三次增加 waiting 队列中 PREEMPTED 状态请求。

结论:最终实现同时统计 running 队列、待重新调度集合、待中止集合以及等待队列中 PREEMPTED 状态的请求,确保所有占用槽位的请求都被计入。 · 已解决

调度器关闭时的错误处理 正确性

修改了 common_engine.py 中对 RuntimeError 的静默处理逻辑。

结论:移除对 "cannot schedule new futures after shutdown" 异常的捕获和忽略,改为重新抛出,确保调度器关闭时的错误能被显式暴露。 · 已解决

风险与影响

  1. 回归风险:修改了调度器的核心准入逻辑,如果新的槽位计数逻辑有误,可能导致调度器过度保守(拒绝本可调度的请求)或过度激进(仍允许超限调度)。
  2. 性能影响:新增了sum([req.status == RequestStatus.PREEMPTED for req in self.waiting])计算,在waiting队列较大时可能增加少量开销。
  3. 兼容性:不涉及API变更,对用户透明。
  4. 测试覆盖:PR body中提到未添加专用单元测试,仅依赖现有测试。Codecov报告显示有1行代码缺少覆盖,需要关注。
  1. 对系统:修复了调度器在高并发、频繁状态转换场景下的槽位计数bug,提升了调度准确性和系统稳定性。
  2. 对用户:在请求频繁被重新调度、中止或抢占的场景下,调度器行为更可预测,避免因过度调度导致的性能下降或错误。
  3. 对团队:修改涉及调度器核心逻辑,需要团队成员理解新的槽位计数规则,并在相关测试中验证。
核心路径变更 缺少测试覆盖

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

执行摘要

  • 一句话:修复调度器在请求状态转换时槽位计数不一致的bug,防止请求无槽位进入运行状态。
  • 推荐动作:该PR值得精读,特别是对于负责调度器模块的工程师。重点关注resource_manager_v1.py中新的槽位计数逻辑设计,这是调度器正确性的关键保障。建议结合近期调度器相关的PR(如#7152、#7129)一起阅读,理解调度器状态的完整演进。

功能与动机

根据PR body描述,修复调度器槽位计数不一致的问题。当请求处于运行、待中止、待重新调度或已抢占回等待队列等状态时,调度器可能过度接纳请求,即使有效占用槽位已达到max_num_seqs,仍将新请求移入running状态。这会导致调度器在接近最大并发数时出现状态不一致。

实现拆解

修改集中在两个核心调度文件:

  1. fastdeploy/engine/sched/resource_manager_v1.py:在_allocate_decode_and_extend函数中,将槽位检查条件从仅检查running队列长度,扩展为同时统计running队列、待重新调度请求集合(to_be_rescheduled_request_id_set)、待中止请求集合(to_be_aborted_req_id_set)以及等待队列中状态为PREEMPTED的请求数量。只有当这些总数小于max_num_seqs时,才允许新请求从waiting进入running。
  2. fastdeploy/engine/common_engine.py:在_fetch_request函数中,移除对RuntimeError("cannot schedule new futures after shutdown")的静默处理,改为直接重新抛出异常,确保调度器关闭时的错误能被显式暴露。

关键文件:

  • fastdeploy/engine/sched/resource_manager_v1.py(模块 Scheduler): 调度器资源管理的核心文件,修改了请求从waiting进入running的准入条件,修复了槽位计数不一致的关键bug。
  • fastdeploy/engine/common_engine.py(模块 Engine): 通用引擎文件,修改了异常处理逻辑,确保调度器关闭时的错误能被正确暴露,避免静默失败。

关键符号:_allocate_decode_and_extend, _fetch_request

评论区精华

Review评论中未提供具体讨论内容。从提交历史看,作者通过三次提交逐步完善了修复:第一次提交添加了基本防护逻辑;第二次提交增加了对to_be_aborted_req_id_set的计数;第三次提交增加了对waiting队列中PREEMPTED状态请求的计数。这表明实现过程中考虑了不同状态请求对槽位占用的影响。

  • 调度器槽位计数逻辑的完整性 (correctness): 最终实现同时统计running队列、待重新调度集合、待中止集合以及等待队列中PREEMPTED状态的请求,确保所有占用槽位的请求都被计入。
  • 调度器关闭时的错误处理 (correctness): 移除对"cannot schedule new futures after shutdown"异常的捕获和忽略,改为重新抛出,确保调度器关闭时的错误能被显式暴露。

风险与影响

  • 风险:1. 回归风险:修改了调度器的核心准入逻辑,如果新的槽位计数逻辑有误,可能导致调度器过度保守(拒绝本可调度的请求)或过度激进(仍允许超限调度)。
    2. 性能影响:新增了sum([req.status == RequestStatus.PREEMPTED for req in self.waiting])计算,在waiting队列较大时可能增加少量开销。
    3. 兼容性:不涉及API变更,对用户透明。
    4. 测试覆盖:PR body中提到未添加专用单元测试,仅依赖现有测试。Codecov报告显示有1行代码缺少覆盖,需要关注。
  • 影响:1. 对系统:修复了调度器在高并发、频繁状态转换场景下的槽位计数bug,提升了调度准确性和系统稳定性。
    2. 对用户:在请求频繁被重新调度、中止或抢占的场景下,调度器行为更可预测,避免因过度调度导致的性能下降或错误。
    3. 对团队:修改涉及调度器核心逻辑,需要团队成员理解新的槽位计数规则,并在相关测试中验证。
  • 风险标记:核心路径变更, 缺少测试覆盖

关联脉络

  • PR #7152 [Feature] Support chunk prefill disabled in scheduler v1: 同样修改了resource_manager_v1.py文件,涉及调度器V1的功能扩展,可结合理解调度器模块的演进。
  • PR #7129 [Feature] Fix mixed cache-aware: 同样涉及调度器修复,虽然修改文件不同(golang_router),但都关注调度逻辑的正确性,可对比学习。
  • PR #7127 [Others]add unit test: 恢复了V1版本缓存管理和资源调度的单元测试,与本次调度器修复相关,建议关注测试覆盖情况。

参与讨论