Prhub

#6270 [worker] feat: support log memory in engine worker

原始 PR 作者 yyyy2000 合并时间 2026-05-12 15:16 文件变更 1 提交数 1 评论 1 代码增减 +7 / -5

执行摘要

engine worker 添加内存日志支持

PR body 明确说明“support log memory in engine worker”,旨在为 engine worker 添加内存使用日志,便于性能监控和调试。

该 PR 变更较小且逻辑清晰,但其 review 讨论揭示了分布式内存监控中的常见陷阱。建议维护者根据 review 意见进一步优化:将 CPU 内存改为进程级测量(使用 psutil.Process().memory_info().rss),并考虑将内存指标置于 all-gather 之前以确保分布式一致性。

讨论亮点

review 中 gemini-code-assist[bot] 提出了两个重点关注:

  1. CPU 内存指标误导性psutil.virtual_memory().used 返回的是整个宿主系统的内存使用量,在多 worker 场景下每个 worker 会报告相同的聚合值,无法区分单个 worker 的占用或定位内存泄漏,建议改为进程级内存测量。
  2. 指标放置位置问题:三个内存指标被放在 allgather_dict_into_dict 调用之后,这意味着最终输出的指标只反映单个 rank 的本地值,而不是经过 all-gather 后的聚合值,对于分布式场景不够准确。此外函数内多次调用 get_torch_device() 存在冗余。

wucong25 审核并两次 APPROVED,未留下评论。

实现拆解

  1. 新增导入依赖:在 verl/workers/engine_workers.py 中增加 import psutilfrom verl.utils.device import get_torch_device,以获取进程级内存信息。
  2. 移除冗余 TODO:删除 _postprocess_output 方法中已被注释掉的三行内存测量占位代码(原先为 TODO 标记)。
  3. 添加内存指标:在 _postprocess_output 方法的末尾,执行完 all-gather 后,新增三个 metric 键值对:
    • perf/max_memory_allocated_gb:GPU 当前分配的显存(GB)。
    • perf/max_memory_reserved_gb:GPU 当前预留的显存(GB)。
    • perf/cpu_memory_used_gb:系统 CPU 总内存使用量(GB)。
  4. 指标收集时机:在分布式 all-gather 之后添加,因此这些指标仅反映单个 rank 的本地值,而非全局聚合值。
文件 模块 状态 重要度
verl/workers/engine_workers.py 引擎工作器 modified 6.01

关键符号

_postprocess_output

关键源码片段

verl/workers/engine_workers.py dependency-wiring

核心变更文件,在 _postprocess_output 中添加了三个内存指标,并新增了 psutil 和 get_torch_device 的导入。

# verl/workers/engine_workers.py (head)
# 在 _postprocess_output 方法末尾添加内存指标记录
# 注意:这些 metric 放在 all-gather 之后,因此只反映本地 rank 的值def _postprocess_output(self, output, *, global_token_num, delta_time, forward_only, images_seqlens):
    # ... 原有的 loss、grad_norm、lr 处理 ...
​
    if dp_group is not None:
        final_metrics = allgather_dict_into_dict(data=metrics, group=dp_group)
    else:
        final_metrics = metrics
​
    if lr is not None:
        final_metrics["lr"] = lr
​
    # 新增:记录 GPU 显存分配量(当前进程分配的显存)
    final_metrics["perf/max_memory_allocated_gb"] = get_torch_device().max_memory_allocated() / (1024**3)
    # 新增:记录 GPU 显存预留量(GPU 驱动预留的显存)
    final_metrics["perf/max_memory_reserved_gb"] = get_torch_device().max_memory_reserved() / (1024**3)
    # 新增:记录系统 CPU 内存使用量(⚠️ 这是系统级,非进程级)
    final_metrics["perf/cpu_memory_used_gb"] = psutil.virtual_memory().used / (1024**3)
​
    # TODO: confirm the mtp loss IS same across dp
    for k, v in final_metrics.items():
        if k.startswith("mtp_losses"):
            # ...

评论区精华

CPU 内存指标应为进程级而非系统级 正确性

gemini-code-assist[bot] 指出 psutil.virtual_memory().used 返回的是整个宿主系统的内存使用量,在多 worker 场景下每个 worker 将报告相同的聚合值,这具有误导性且无法用于定位单 worker 的内存泄漏。建议使用 psutil.Process().memory_info().rss 获取进程级内存。

结论:未在 PR 中修复,但 review 已指出此问题,后续可跟进优化。 · unresolved

风险与影响

  1. 指标准确性风险:CPU 内存使用量使用系统级 psutil.virtual_memory().used,在多 worker 同机部署时每个 worker 报告相同值,可能误导运维决策。
  2. 分布式一致性风险:指标在 all-gather 后添加,不会参与分布式归约,导致最终输出的内存指标仅来自单个 rank,在多节点场景下可能不具代表性。
  3. 依赖新增风险:引入 psutil 库,如果环境未安装可能导致运行时 ImportError;但该库为常见系统监控库,风险较低。

对用户和系统的影响较小:

  • 用户影响:训练日志中会新增三个内存相关的 metric,有助于性能分析和诊断。
  • 系统影响:仅新增三次函数调用和一次库导入,对性能无实质性影响。
  • 团队影响:提供更丰富的监控指标,但指标定义需要后续澄清(如 CPU 内存是否应为进程级)。
准确性顾虑 缺少测试覆盖

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论