Prhub

#47420 [Core][DP] Rotate load-balancer tie-break to avoid systematic engine bias

原始 PR 作者 mayuyuace 合并时间 2026-07-06 15:09 文件变更 1 提交数 4 评论 2 代码增减 +6 / -0

执行摘要

DP 负载均衡器轮转起始索引消除系统偏差

在 DP 负载均衡器 DPLBAsyncMPClient.get_core_engine_for_request 中,选择引擎时使用固定的 eng_start_index 和严格 < 比较,导致引擎得分相同时总是选择第一个扫描到的引擎。当协调器广播更新全局统计时,引擎得分经常持平,固定 tie-break 使同一引擎持续获得请求,造成负载不均衡,增加尾延迟和总运行时间。

值得合并。变更极小但效果明显,是典型的低风险高收益优化。

讨论亮点

无显著讨论。njhill 审核后直接批准,评论“looks fine to me”。

实现拆解

  1. 确定问题根源:在 vllm/v1/engine/core_client.pyget_core_engine_for_request 方法中,引擎选择循环从固定的 eng_start_index 开始扫描,使用 < 比较得分。当多个引擎得分相同时,总是选中第一个扫描到的引擎,即 eng_start_index(对于单前端客户端为 0)。
  2. 引入轮转机制:每次调用 get_core_engine_for_request 并经过负载均衡选择后,将 eng_start_index 加 1 对引擎数取模,使下一次扫描从下一个引擎开始。这样,在得分持平的情况下,选中的引擎会轮转,从而均匀分布请求。
  3. 保持负载感知不变:得分不同时,仍会选择得分最低的引擎,原有负载感知逻辑不受影响。
文件 模块 状态 重要度
vllm/v1/engine/core_client.py 引擎客户端 modified 6.37

关键符号

get_core_engine_for_request

关键源码片段

vllm/v1/engine/core_client.py core-logic

核心变更文件,修改了负载均衡器的 tie-break 行为,新增轮转起始索引逻辑。

# vllm/v1/engine/core_client.py - DPLBAsyncMPClient.get_core_engine_for_request
​
    # ... 前面省略
    for i in range(num_engines):
        # ... 选出得分最低的引擎
        idx = (self.eng_start_index + i) % num_engines
        waiting, running = current_counts[idx]
        score = waiting * 4 + running
        if score < min_score:
            min_score = score
            eng_index = idx
    # 增加本地等待计数以补偿协调器广播延迟(约 100ms)
    current_counts[eng_index][0] += self.client_count
​
    # 轮转扫描起始索引,使得分相同时的 tie-break 均匀分布到各个引擎
    self.eng_start_index = (self.eng_start_index + 1) % num_engines
​
    chosen_engine = self.core_engines[eng_index]
    # ... 后续不变

评论区精华

没有提炼出高价值讨论线程

当前评论区没有形成足够清晰的争议点或结论,后续有更多讨论时会体现在这里。

风险与影响

风险极低:变更仅增加一行状态更新代码,逻辑简单清晰,不影响现有协议、配置或并发模型。可能存在细微的性能影响(溢出、取模运算),但可以忽略。

影响范围限制在 DP 负载均衡器的内部决策逻辑。对用户透明,但能显著改善 DP 场景下的请求分布均匀性,降低尾延迟,提升吞吐量。

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论