Prhub

#25438 Convert forward_pass_device_timer to None-init

原始 PR 作者 fzyzcjy 合并时间 2026-05-16 09:20 文件变更 1 提交数 1 评论 1 代码增减 +4 / -2

执行摘要

将 forward_pass_device_timer 初始化为 None

PR body 指出 forward_pass_device_timer 之前仅在启用设备定时器指标时条件赋值,导致读取点必须用 hasattr 防御属性不存在的情况。将其无条件初始化为 None 并用 is None 守卫,使真正的不变性(启用设备定时器指标时有值,否则为 None)直接体现在类型中。

可以合并。这是一个小型机械重构,提升了代码可维护性,无功能变化。

讨论亮点

本 PR 无 review 讨论。

实现拆解

  1. SchedulerMetricsMixin.__init__ 中,处于 if ENABLE_METRICS_DEVICE_TIMER: 条件赋值之前,添加一行 self.forward_pass_device_timer: Optional[DeviceTimer] = None,确保属性始终存在。
  2. install_device_timer_on_runners 方法中,将守卫条件从 if not hasattr(self, "forward_pass_device_timer"): return 改为 if self.forward_pass_device_timer is None: return
  3. _init_fpm 方法中,将读取点的 if hasattr(self, "forward_pass_device_timer"): 改为 if self.forward_pass_device_timer is not None:
文件 模块 状态 重要度
python/sglang/srt/observability/scheduler_metrics_mixin.py 调度指标 modified 5.94

关键符号

__init__ install_device_timer_on_runners _init_fpm

关键源码片段

python/sglang/srt/observability/scheduler_metrics_mixin.py core-logic

唯一变更文件,包含条件初始化添加和两处守卫替换,是整个 PR 的核心。

# python/sglang/srt/observability/scheduler_metrics_mixin.py (head)class SchedulerMetricsMixin:
    def init_metrics(self, ...):
        # ... 前面的初始化代码 ...
​
        self.fwd_occupancy = float("nan")
​
        # [ 新增 ] 无条件初始化为 None,确保属性始终存在
        self.forward_pass_device_timer: Optional[DeviceTimer] = None
​
        if ENABLE_METRICS_DEVICE_TIMER:
            self._device_timer_window_batch_count = 0
            self._device_timer_window_gpu_time = 0.0
            self._device_timer_window_start = None
​
            def _wrap_execution_reporter(**kwargs):
                self._device_timer_window_gpu_time += kwargs["t"]
                if self.enable_metrics:
                    self.metrics_collector.increment_forward_execution_seconds(**kwargs)
​
            self.forward_pass_device_timer = DeviceTimer(
                reporter=_wrap_execution_reporter,
            )
​
        # ... 剩余初始化代码 ...
​
    def install_device_timer_on_runners(self: Scheduler):
        # [ 修改 ] 用 is None 替代 hasattr,更直接表达语义
        if self.forward_pass_device_timer is None:
            return
        timer = self.forward_pass_device_timer
        self.tp_worker.model_runner.device_timer = timer
        # ... 注入到 draft worker 的代码 ...
​
    def _init_fpm(self: Scheduler):
        # ...
        def _fpm_device_timer_reporter(t, **_kwargs):
            self._fpm_gpu_time_acc += t
​
        # [ 修改 ] 同样用 is not None 替代 hasattr
        if self.forward_pass_device_timer is not None:
            self.forward_pass_device_timer.add_reporter(_fpm_device_timer_reporter)
        else:
            self.forward_pass_device_timer = DeviceTimer(
                reporter=_fpm_device_timer_reporter,
            )
        self._fpm_uses_device_timer = True
        # ...

评论区精华

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

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

风险与影响

风险极低。变更仅涉及两个守卫条件和一个无条件初始化,逻辑等价。如果 forward_pass_device_timer__init__ 外被删除或重写,可能导致 is None 守卫无法正确处理,但这种用法在代码库中不存在。未引入新的 import 或外部依赖。

直接影响 SchedulerMetricsMixin 及其子类,以及 install_device_timer_on_runners 的调用方。对系统行为无影响,是纯粹的重构。

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论