执行摘要
- 一句话:转换 grad_norm 为标量避免 Ray 序列化崩溃
- 推荐动作:建议合并,改动小而精确。可考虑在类似度量(如
lr)上也做防御性转换以增加鲁棒性。
功能与动机
训练时因 Ray 尝试在 CPU-only 节点上反序列化 CUDA Tensor 而崩溃(错误:torch.cuda.is_available() is False),根因是 grad_norm 保留为 Tensor 类型未转换。
实现拆解
- 修改文件:
verl/workers/engine_workers.py 中的 _postprocess_output 方法。
- 逻辑变更:在
metrics.pop("grad_norm", None) 后,增加 isinstance(grad_norm, torch.Tensor) 判断,若为 Tensor 则通过 .detach().item() 转为 Python float。
- 无其他改动:初版中涉及 LoRA 权重同步的无关删除(
sleep_level、base_sync_done)经 reviewer 指出后由作者回退,最终仅保留该 2 行防御性转换。
关键文件:
verl/workers/engine_workers.py(模块 工作进程;类别 source;类型 core-logic;符号 _postprocess_output): 唯一变更文件,在 _postprocess_output 中添加 Tensor 转标量逻辑,是修复的核心。
关键符号:_postprocess_output
关键源码片段
verl/workers/engine_workers.py
唯一变更文件,在 _postprocess_output 中添加 Tensor 转标量逻辑,是修复的核心。
# 文件 : verl/workers/engine_workers.py,位于 _postprocess_output 方法内
# For grad_norm, we do not perform all reduce because it is already been done when clipping grad
grad_norm = metrics.pop("grad_norm", None)
if isinstance(grad_norm, torch.Tensor):
grad_norm = grad_norm.detach().item() # 转为 Python 标量避免 Ray 在 CPU 节点上反序列化出错
lr = metrics.pop("lr", None)
# ... 后续逻辑保持不变 ...
if grad_norm is not None:
final_metrics["grad_norm"] = grad_norm
评论区精华
风险与影响
- 风险:风险极低:变更仅为 2 行防御性代码,仅在
grad_norm 为 Tensor 时生效,对原有逻辑无副作用。但若 grad_norm 为其他不可序列化类型(如 numpy array)则不会处理,不过当前路径中仅可能出现 Tensor 或 None。
- 影响:影响范围限于使用 Megatron-Core 最新版且
grad_norm 返回 Tensor 的训练任务。对其他用户无感知,修复后训练可正常进行。
- 风险标记:序列化错误风险, 缺乏测试覆盖
关联脉络
参与讨论