Prhub

#6430 [misc] fix: device variable not bound in some scripts

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

执行摘要

修复 GRPO shell 脚本中 DEVICE 变量未初始化

脚本使用 set -u 且已有 case "${DEVICE}" 分支,但 DEVICE 未初始化,shell 因未绑定变量而立即退出,导致 Python 侧 auto_device 逻辑无法执行。PR 作者在评论中解释:'The script uses set -u and already has case "${DEVICE}" in ... If DEVICE is not initialized, shell exits immediately.' 此变更旨在提供 shell 层默认值并保持与其它示例脚本行为一致。

此 PR 为小范围 bug 修复,简单直接,值得快速合并。代码审查中提出的风险(stdout 污染、硬件可用性检测)在实际使用中可能性较低(torch_npu 在标准安装下不输出 stdout 信息),且社区已有类似用法,可接受。建议未来对类似自动检测逻辑进行统一抽象。

讨论亮点
  • reviewer tardis-key 询问:'Does auto_device not work properly? If it works fine, there's no need to specify DEVICE in the script.' 作者 zjchenn 回复解释 auto_device 在 Python 入口启动后才生效,而失败发生在 shell 脚本中 set -u 阶段,因此需要 shell 级默认值。
  • gemini-code-assist[bot] 提出两条高优先级评论(两条文件各一条),指出当前检测逻辑可能将 torch_npu 的初始化输出捕获到 DEVICE 变量中,且仅仅导入包不能保证硬件可用。建议使用更安全的检测方式如 torch.npu.is_available()。此建议未被采纳,PR 以当前形式合并。

实现拆解

  1. 添加变量默认值:在两个 run_*.sh 脚本的用户可调参数区域内,在已有的 INFER_BACKENDMODEL_PATH 等变量之上,新增一行 DEVICE 的默认赋值。
  2. 自动检测逻辑:使用 ${DEVICE:-$(python3 -c 'import torch_npu' 2>/dev/null && echo npu || echo gpu)},如果用户未设置 DEVICE 环境变量,则尝试导入 torch_npu(将 stderr 重定向到 /dev/null),若成功则默认 npu,否则 gpu
  3. 向后兼容:用户仍可通过在脚本执行前 export DEVICE=gpuexport DEVICE=npu 显式覆盖自动检测结果。
  4. 文件范围:仅修改 examples/grpo_trainer/run_qwen2_5_32b_fsdp.shexamples/grpo_trainer/run_qwen3_4b_fsdp.sh,无其他配置、测试或文档改动。
文件 模块 状态 重要度
examples/grpo_trainer/run_qwen2_5_32b_fsdp.sh 示例脚本 modified 2.71
examples/grpo_trainer/run_qwen3_4b_fsdp.sh 示例脚本 modified 2.71

关键源码片段

examples/grpo_trainer/run_qwen2_5_32b_fsdp.sh core-logic

第一个被修复的 GRPO 训练脚本,因 set -u 导致 DEVICE 未绑定而崩溃。添加了自动检测默认值。

# ---- user-adjustable ----
# DEVICE is auto-detected by probing torch_npu; override only for special cases.
DEVICE=${DEVICE:-$(python3 -c 'import torch_npu' 2>/dev/null && echo npu || echo gpu)}
INFER_BACKEND=${INFER_BACKEND:-vllm}
MODEL_PATH=${MODEL_PATH:-Qwen/Qwen2.5-32B}
# ... 后续 case "${DEVICE}" 分支
examples/grpo_trainer/run_qwen3_4b_fsdp.sh core-logic

第二个被修复的 GRPO 训练脚本,与 run_qwen2_5_32b_fsdp.sh 相同的修复。

# ---- user-adjustable ----
# DEVICE is auto-detected by probing torch_npu; override only for special cases.
DEVICE=${DEVICE:-$(python3 -c 'import torch_npu' 2>/dev/null && echo npu || echo gpu)}
INFER_BACKEND=${INFER_BACKEND:-vllm}
MODEL_PATH=${MODEL_PATH:-Qwen/Qwen3-4B}
# ... 后续 case "${DEVICE}" 分支

评论区精华

是否需要 shell 级 DEVICE 默认值 question

tardis-key 询问 auto_device 是否正常工作,暗示若 Python 侧能自动检测则无需 shell 变量。

结论:作者解释 auto_device 在 Python 入口后才生效,而脚本中 set -u 在 shell 阶段就失败,因此需要 shell 级默认值。 · 已解决

自动检测逻辑的安全性 正确性

gemini-code-assist[bot] 指出当前命令可能捕获 torch_npu 的 stdout 输出到 DEVICE 变量,且仅仅 import 不能保证硬件可用。建议使用 torch.npu.is_available() 等更安全的方式。

结论:PR 未采纳建议,以当前形式合并。风险被评估为低概率,且已有类似用法。 · unresolved

风险与影响

  1. 初始化输出污染python3 -c 'import torch_npu' 可能向 stdout 打印初始化信息,导致 DEVICE 变量包含非预期内容(如 "Loading...npu"),使后续 case 匹配失败。当前已将 stderr 重定向到 /dev/null,但无法完全避免某些框架向 stdout 输出。
  2. 仅导入不保证硬件可用:单纯导入 torch_npu 成功不代表 NPU 设备已就绪,可能导致在 NPU 不可用时仍误判为 npu
  3. 影响范围小:只影响两个 shell 脚本,且是可选默认值,风险较低。
  • 用户:使用这两个脚本的用户无需手动设置 DEVICE,脚本可自动适配 GPU/NPU 环境,降低使用门槛。
  • 系统:仅 shell 脚本层面改动,不影响 Python 核心逻辑或运行时。
  • 团队:与 verl 项目中其他示例脚本风格一致,维护成本低。
潜在 stdout 污染

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论