PBS系统中subprocess.call无法多节点运行的问题求助
多节点PBS任务中MPIRUN运行VASP报错的解决方法
问题描述
通过PBS的qsub提交任务,分配2个节点(cu25:ppn=32+cu26:ppn=32),期望Python脚本中的subprocess.call调用mpirun vasp_std在多节点上运行,但出现PSM2设备无法打开的报错,单节点运行正常。
用户提供的脚本及报错
PBS脚本(run.pbs)
#!/bin/bash #PBS -N test-cpu #PBS -l nodes=cu25:ppn=32+cu26:ppn=32 #PBS -l walltime=720:00:00 #PBS -q batch #PBS -j oe cd $PBS_O_WORKDIR NPROCS=`wc -l < $PBS_NODEFILE` python3 run.py
Python脚本(run.py)
import subprocess command = "mpirun vasp_std" with open('vasp.out', 'w') as f: subprocess.call(command, shell=True, stdout=f, cwd=None)
报错信息
cu25.115070PSM2 can't open hfi unit: -1 (err=23) cu26.99380PSM2 can't open hfi unit: -1 (err=23) cu26.100027PSM2 can't open hfi unit: -1 (err=23) cu25.114979PSM2 can't open hfi unit: -1 (err=23) cu25.114926PSM2 can't open hfi unit: -1 (err=23) cu25.115487PSM2 can't open hfi unit: -1 (err=23) cu25.114932PSM2 can't open hfi unit: -1 (err=23) [mpiexec@cu25] HYDU_sock_write (../../utils/sock/sock.c:418): write error (Bad file descriptor) [mpiexec@cu25] HYD_pmcd_pmiserv_send_signal (../../pm/pmiserv/pmiserv_cb.c:253): unable to write data to proxy [mpiexec@cu25] ui_cmd_cb (../../pm/pmiserv/pmiserv_pmci.c:175): unable to send signal downstream [mpiexec@cu25] HYDT_dmxu_poll_wait_for_event (../../tools/demux/demux_poll.c:76): callback returned error status [mpiexec@cu25] HYD_pmci_wait_for_completion (../../pm/pmiserv/pmiserv_pmci.c:507): error waiting for event [mpiexec@cu25] main (../../ui/mpich/mpiexec.c:1148): process manager error waiting for completion [mpiexec@cu25] HYDU_sock_write (../../utils/sock/sock.c:418): write error (Bad file descriptor)
解决方案
1. 让MPI正确读取PBS分配的节点信息
PBS会生成$PBS_NODEFILE文件记录已分配的节点和核数,mpirun需要指定该文件才能在多节点上正确调度进程,同时要指定总进程数-np $NPROCS:
- 修改PBS脚本,将
NPROCS传递给Python:# PBS脚本中替换python3 run.py为: python3 run.py $NPROCS - 修改Python脚本,接收参数并更新
mpirun命令:import subprocess import sys if len(sys.argv) < 2: print("Error: Please pass NPROCS as argument") sys.exit(1) nprocs = sys.argv[1] command = f"mpirun -np {nprocs} --hostfile $PBS_NODEFILE vasp_std" with open('vasp.out', 'w') as f: subprocess.call(command, shell=True, stdout=f, cwd=None)
2. 避免硬编码节点,使用动态分配
直接指定节点可能导致目标节点的HFI设备被占用,改为让PBS调度系统自动分配可用节点:
# 修改PBS中的节点分配行: #PBS -l nodes=2:ppn=32
3. 确保加载正确的MPI/PSM2环境模块
部分集群需要显式加载MPI通信库模块才能正常使用PSM2,在PBS脚本中添加模块加载命令:
# 在cd $PBS_O_WORKDIR后添加: module load intel-mpi # 替换为集群实际使用的MPI模块名称
4. 简化流程,直接在PBS脚本中调用mpirun
跳过Python subprocess,直接在PBS脚本中执行mpirun,避免环境变量传递问题:
# PBS脚本中替换python3 run.py为: mpirun -np $NPROCS --hostfile $PBS_NODEFILE vasp_std > vasp.out 2>&1
内容的提问来源于stack exchange,提问作者zihao jiao
相关产品推荐
相关产品推荐

