使用Ray时如何将ssh节点启动脚本改造为pbsdsh版本
PBS集群pbsdsh启动Ray跨节点集群适配方案
报错核心原因
- pbsdsh和SSH的执行逻辑完全不同:pbsdsh拉起的远端进程默认不继承当前交互shell加载的conda环境、自定义PATH变量,也不会自动切换到作业工作目录,你遇到的exit status 254本质是远端节点执行命令时找不到Ray依赖、环境加载失败,不是Ray本身的通信逻辑问题。
mpiprocs=24时报错重复48次,是因为pbsdsh默认会在PBS分配的每一个CPU槽位上启动一次任务,2个节点*24槽位正好触发48次执行——Ray每个计算节点只需要启动1个工作进程,不需要按核数重复拉起。
可直接复用的适配步骤
- 作业脚本开头先固定所有全局变量,不要依赖动态继承的环境值
# 从PBS节点文件中读取去重后的节点列表 NODES=($(cat $PBS_NODEFILE | uniq)) HEAD_NODE=${NODES[0]} # 固定Ray头节点通信端口,避免随机端口被集群内网防火墙拦截 RAY_PORT=6379 HEAD_ADDR="${HEAD_NODE}:${RAY_PORT}" # 替换为你自己的conda环境绝对路径,不要用环境名 CONDA_ENV_ABS_PATH="/data/xxx/miniconda3/envs/ray_train" # 替换为你的训练代码所在绝对路径 CODE_DIR="/data/xxx/train_project" # 单节点可用CPU核数,和你PBS申请的mpiprocs保持一致 PER_NODE_CPU=24
- 拉起Ray头节点服务,必须显式绑定节点物理IP
# 头节点本地启动服务,禁止绑定127.0.0.1,否则跨节点无法访问 ssh ${HEAD_NODE} " source ${CONDA_ENV_ABS_PATH}/bin/activate cd ${CODE_DIR} ray start --head --node-ip-address=${HEAD_NODE} --port=${RAY_PORT} --num-cpus=${PER_NODE_CPU} & " # 等待10秒确保头节点服务完全初始化 sleep 10
- 用pbsdsh逐节点拉起工作进程,关键参数不能漏
# 跳过第一个头节点,遍历剩余所有工作节点 for worker in ${NODES[@]:1} do # -u 参数指定每个目标节点只启动1个进程,避免按CPU槽位重复执行 # -h 参数指定只在当前目标worker节点执行命令 pbsdsh -u -h ${worker} " source ${CONDA_ENV_ABS_PATH}/bin/activate cd ${CODE_DIR} ray start --address=${HEAD_ADDR} --num-cpus=${PER_NODE_CPU} " done
- 所有节点启动完成后,验证集群状态后提交训练任务
source ${CONDA_ENV_ABS_PATH}/bin/activate cd ${CODE_DIR} python -c "import ray; ray.init(address='auto'); print(ray.cluster_resources())" python example_trainer.py
常见踩坑排查
- 不要裸用pbsdsh不加
-h指定节点,否则会在所有分配节点(包括头节点)重复执行启动命令,引发端口冲突、集群状态异常。 - 不要在pbsdsh执行块里用
conda activate 环境名,pbsdsh拉起的是非交互shell,没有加载conda初始化脚本,必须用conda环境的绝对路径source激活。 - 启动Ray时必须显式传
--node-ip-address参数,否则Ray默认绑定本地回环地址,跨节点通信会直接超时。 - PBS作业脚本不要加
#PBS -V参数,该参数会把登录节点的环境变量强行同步到计算节点,容易触发glibc、cuda等动态库版本冲突。 - 如果仍报254错误,可在pbsdsh执行块里加
echo $PATH > /tmp/pbsdsh_debug_${worker}.log,到对应节点查看日志,确认conda环境的bin目录是否在PATH中即可快速定位问题。
内容的提问来源于stack exchange,提问作者Muhammad Nasir
相关产品推荐
相关产品推荐

