Prhub

#2027 Only upload per sample stats to wandb

原始 PR 作者 zhuzilin 合并时间 2026-06-08 19:26 文件变更 15 提交数 8 评论 0 代码增减 +461 / -204

执行摘要

将 wandb 指标上传改为仅基于 per-sample 统计

之前的方案通过 reinit_wandb_primary_with_open_metrics 在 wandb 中开启 stats monitor 抓取 sglang 的 Prometheus 端点,会上传大量服务器级指标(如 GPU 内存、KV cache 等),数据量大且非 per-sample 级别。新方案从 sglang 生成的 trace 中提取每个请求的性能指标,计算统计后上传,更精准且减轻 wandb 负载。

建议仔细阅读 _compute_sglang_request_perf_metrics_iter_sglang_generate_attrs 的实现,理解从 trace 提取指标的模式。若当前使用服务器端 wandb 指标,需评估移除影响并调整监控策略。关注 sglang.patch 的版本兼容性。

讨论亮点

未发现正式 review 评论。从提交历史(8 次提交,含 revert 和 fix)可见开发过程中有反复调试,特别是在 PD 时序字段的命名与 sglang patch 整合上经历了调整。

实现拆解

  1. slime/ray/rollout.py 中新增 per-sample 指标收集:定义 _SGLANG_REQUEST_PERF_FIELDS_SGLANG_PREFILL_PERF_FIELDS_SGLANG_DECODE_PERF_FIELDS 常量元组,从 trace attributes 映射到 wandb 指标名称;新增 _iter_sglang_generate_attrs 生成器提取每个样本的 attrs;新增 _compute_sglang_request_perf_metrics 函数遍历所有样本,调用内部函数 add_value 收集有效数值,最后通过 compute_statistics 计算统计量并返回汇总词典。compute_perf_metrics_from_samples 末尾会调用新函数合并结果。
  2. 移除旧服务器端指标采集:删除 slime/utils/wandb_utils.py 中的 reinit_wandb_primary_with_open_metrics 函数(约 56 行),该函数通过重新初始化 wandb 并配置 x_stats_open_metrics_endpoints 抓取 sglang 路由器的 Prometheus 指标;删除 slime/utils/logging_utils.py 中的 update_tracking_open_metrics 函数;更新 train.pytrain_async.py,移除对应调用。
  3. 更新 sglang patch:在 docker/patch/latest/sglang.patch 中增加对 PD 分解时序的支持,包括在 KV 传递链中新增 prefill_timing 辅助缓冲区、定义 PREFILL_TIMING_DEST_ATTRS 字段列表、decode 端超时检测;同时修复字段命名不一致问题(如 fwd_bootstrap_durationfwd_prefill_bootstrap_duration)。
  4. 完善 trace 字段映射:在 slime/utils/trace_utils.pySGLANG_TRACE_META_KEYS 中添加新字段(如 queue_time, e2e_latency, decode_throughput, pd_prefill_bootstrap_duration 等),并在 build_sglang_meta_trace_attrs 中增加 sglang_request_id
  5. 更新 timeline viewer:在 tools/trace_timeline_viewer.py 中修正 PD lane spec 字段名、在图例和颜色常量中补充 decode 侧 bootstrap/alloc_wait 字段,支持新分解视图。
  6. 新增文档:添加 docs/en/advanced/observability.mddocs/zh/advanced/observability.md,介绍 wandb 可观测性配置。
  7. Dockerfile 微调:更新镜像版本或依赖。
文件 模块 状态 重要度
slime/ray/rollout.py rollout 层 modified 8.12
slime/utils/wandb_utils.py W&B 工具 modified 7.3
docker/patch/latest/sglang.patch SGLang 补丁 modified 6.48
slime/utils/trace_utils.py Trace 工具 modified 5.62
tools/trace_timeline_viewer.py 可视化工具 modified 6.13
train.py 入口脚本 modified 5.59
train_async.py 异步入口 modified 5.59
slime/utils/logging_utils.py 日志工具 modified 5.49
docs/en/advanced/observability.md 英文文档 added 4.25
docs/zh/advanced/observability.md 中文文档 added 4.24
docker/Dockerfile Docker 配置 modified 2.64

关键符号

_compute_sglang_request_perf_metrics _iter_sglang_generate_attrs add_value compute_perf_metrics_from_samples build_sglang_meta_trace_attrs reinit_wandb_primary_with_open_metrics (removed) update_tracking_open_metrics (removed)

关键源码片段

slime/ray/rollout.py core-logic

核心变更文件:新增 per-sample 性能指标收集和聚合函数,改变 wandb 指标上传粒度

def _compute_sglang_request_perf_metrics(all_samples: list[Sample]):
    # 从所有样本中收集 sglang generate attrs,提取性能指标并计算统计值
    attrs_by_request = list(_iter_sglang_generate_attrs(all_samples))
    if not attrs_by_request:
        return {}
​
    values_by_metric: dict[str, list[float]] = {}
    profiled_request_count = 0
​
    def add_value(metric_key: str, source_key: str, attrs: dict) -> bool:
        # 尝试从 attrs 中提取数值,如果有效则加入列表
        value = attrs.get(source_key)
        if not isinstance(value, (int, float)) or isinstance(value, bool) or not np.isfinite(value):
            return False
        values_by_metric.setdefault(metric_key, []).append(float(value))
        return True
​
    for attrs in attrs_by_request:
        request_has_perf = False
        # 依次处理请求级、prefill 级、decode 级指标
        for metric_key, source_key in _SGLANG_REQUEST_PERF_FIELDS:
            request_has_perf |= add_value(metric_key, source_key, attrs)
        for metric_key, source_key in _SGLANG_PREFILL_PERF_FIELDS:
            request_has_perf |= add_value(metric_key, source_key, attrs)
        for metric_key, source_key in _SGLANG_DECODE_PERF_FIELDS:
            request_has_perf |= add_value(metric_key, source_key, attrs)
        if request_has_perf:
            profiled_request_count += 1
​
    metrics: dict[str, float] = {
        "request/count": len(attrs_by_request),
        "request/profiled_count": profiled_request_count,
    }
    # 对每个指标汇总统计量(平均值、标准差等),并扁平化命名
    for key, values in values_by_metric.items():
        if not values:
            continue
        metrics |= dict_add_prefix(compute_statistics(values), f"{key}/")
        metrics[f"{key}/count"] = len(values)
​
    return metrics

评论区精华

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

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

风险与影响

  1. 依赖 sglang trace 的生成;若 sglang 版本不兼容或未正确启用 trace,per-sample 指标会缺失。
  2. 移除 reinit_wandb_primary_with_open_metrics 后,依赖服务器端指标(如 GPU 内存、KV cache 使用率)的用户将无法获取这些数据。
  3. sglang.patch 需与 sglang 版本精确匹配,升级 sglang 时可能需同步更新 patch。
  4. 字段命名变更(如 pd_bootstrap_durationpd_prefill_bootstrap_duration)可能影响已有监控仪表板或告警规则。

对用户:wandb 仪表板不再显示服务器级指标,转而展示 per-sample 性能指标(请求延迟、吞吐量、PD 分解时序),粒度更细但范围缩小。对系统:减少 wandb 上传数据量,降低网络和 wandb 服务压力。对团队:需更新监控仪表板和告警规则;调试时可通过增强的 trace 字段定位性能瓶颈。

移除服务器端指标 依赖 sglang trace 字段名称变更 补丁版本兼容性

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论