Prhub

#29207 Add scheduler metrics extension hooks

原始 PR 作者 merrymercy 合并时间 2026-06-25 06:50 文件变更 4 提交数 1 评论 4 代码增减 +52 / -10

执行摘要

添加调度器指标扩展钩子,支持模型特定 SoL 统计

为了更精确地报告预填充阶段的性能指标,避免壁钟时间与 GPU 实际执行时间不一致导致的偏差,需要为模型子类提供扩展点,使其能根据批次中的请求级别数据(如 extend/prefix 长度)计算精确的 attention 操作对数量,并输出 SoL 百分比。同时,需要区分 target_verify 和 extend 阶段的定时器范围,以正确归因性能数据。

该 PR 值得精读,它展示了如何通过钩子模式为内部系统添加可扩展性,同时注意保留必要数据供异步处理器使用。关注点在 MetricsReporter 中的覆写方法和 ScheduleBatch.copy 的数据保留策略。

讨论亮点

该 PR 没有 review 评论,讨论可能集中在内部。

实现拆解

  1. ScheduleBatch.copy 方法中,添加 extend_lensprefix_lens 的深拷贝(schedule_batch.py),使得在异步指标报告时保留原始请求的 extend/prefix 长度。
  2. 修改 MetricsReporter._estimate_prefill_perf 接口,改为接收 batch 对象并从 batch.extend_lens 计算 token 总数(metrics_reporter.py),从而利用拷贝时保存的精确扩展长度。
  3. MetricsReporter 中添加 _prefill_sol_suffix_decode_sol_suffix 钩子方法,默认返回空字符串(metrics_reporter.py),子类可覆写以提供模型特定的 SoL 百分比。
  4. report_prefill_stats 中,如果 _prefill_sol_suffix 返回非空字符串,则直接附加到日志行,并跳过估算 TFLOPS 的计算;否则仍使用原有估算逻辑。在 report_decode_stats 中类似调用 _decode_sol_suffix
  5. model_runner.pyeager_runner.py 的 device_timer 包装中,根据 forward_batch.forward_mode.is_target_verify() 区分 category 为 "target_verify""extend",使得定时器统计能正确区分目标验证和常规扩展阶段。
文件 模块 状态 重要度
python/sglang/srt/managers/scheduler_components/metrics_reporter.py 指标报告 modified 8.02
python/sglang/srt/managers/schedule_batch.py 调度器 modified 5.75
python/sglang/srt/model_executor/model_runner.py 模型运行器 modified 5.61
python/sglang/srt/model_executor/runner/eager_runner.py 运行器 modified 5.61

关键符号

_estimate_prefill_perf _prefill_sol_suffix _decode_sol_suffix copy (ScheduleBatch) _forward_raw _execute_extend

关键源码片段

python/sglang/srt/managers/schedule_batch.py data-contract

在 ScheduleBatch.copy 中添加 extend_lens 和 prefix_lens 的快照,确保延迟指标报告能获取原始请求的扩展 / 前缀长度

# 在 ScheduleBatch.copy 方法中
return ScheduleBatch(
    reqs=self.reqs[:],
    # 保留 extend_lens 和 prefix_lens 的快照
    # 使得在原始 batch 被修改后,延迟指标报告仍可读取这些值
    extend_lens=self.extend_lens[:] if self.extend_lens is not None else None,
    prefix_lens=self.prefix_lens[:] if self.prefix_lens is not None else None,
    # 其他字段不变 ...
    req_to_token_pool=self.req_to_token_pool,
    # ...
)
python/sglang/srt/model_executor/model_runner.py data-contract

在 prefill cuda graph 路径中将 device_timer category 从固定的 "extend" 改为根据 forward_mode 判断 "target_verify" 或 "extend"

# 在 ModelRunner._forward_raw 中
elif (
    forward_batch.forward_mode.is_extend(include_draft_extend_v2=True)
    and not isinstance(self.prefill_cuda_graph_runner, EagerRunner)
    and self.prefill_cuda_graph_runner is not None
    and self.prefill_cuda_graph_runner.can_run_graph(forward_batch)
    and get_cp_strategy() is None
):
    # 区分 target_verify 和 extend
    category = (
        "target_verify"
        if forward_batch.forward_mode.is_target_verify()
        else "extend"
    )
    # ...
    ctx = (
        self.device_timer.wrap(metadata={"category": category})
        if self.device_timer
        else contextlib.nullcontext()
    )
    with ctx:
        ret = self.prefill_cuda_graph_runner.execute(
            forward_batch, **kwargs
        )
python/sglang/srt/model_executor/runner/eager_runner.py data-contract

在 eager 模式中类似修改 device_timer category,以区分 target_verify 和 extend

# 在 EagerRunner._execute_extend 中
category = (
    "target_verify"
    if forward_batch.forward_mode.is_target_verify()
    else "extend"
)
ctx = (
    model_runner.device_timer.wrap(metadata={"category": category})
    if model_runner.device_timer
    else contextlib.nullcontext()
)
with ctx:
    # ... 继续执行 model.forward

评论区精华

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

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

风险与影响

主要风险包括:1)_estimate_prefill_perf 的参数类型从 int 改为 batch 对象,任何直接调用此方法的子类或外部代码需要更新;2)新增的 extend_lensprefix_lens 拷贝增加了 batch copy 的内存开销,但仅为两个 list 的浅拷贝,影响很小;3)device-timer category 的区分可能影响现有监控面板,如果已有基于 "extend" 类别的汇总统计,需要确认 target_verify 的分离是否匹配预期。

对用户透明:不改变任何外部 API 或行为。对系统:扩展点的添加使得未来可以更灵活地添加模型特定指标。对团队:指标报告更精确,有助于性能分析和优化。影响范围:仅限于指标报告模块,不影响核心推理路径。

接口向后兼容 无专用测试覆盖 批次拷贝开销小

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论