SLURM系统中Python脚本调用全核心OpenFOAM的多进程实现求助
解决SLURM系统中Python包装器调用OpenFOAM多进程问题
核心问题分析
当前Python脚本由mpirun -np 4启动(对应4个节点各1个MPI进程),直接调用工具会继承MPI环境限制,导致进程数不足;嵌套mpirun或使用mpi4py Spawn会因资源冲突/环境限制失败。以下是可行解决方案:
方法一:用SLURM原生srun启动全CPU进程
利用SLURM环境变量获取总CPU数,仅在主MPI进程(rank=0)调用srun启动OpenFOAM,避免MPI环境冲突:
import subprocess import os from mpi4py import MPI comm = MPI.COMM_WORLD rank = comm.Get_rank() if rank == 0: # 从SLURM环境变量自动获取总CPU数, fallback到80 total_cpus = int(os.environ.get('SLURM_NTASKS', 80)) # srun直接对接SLURM资源,--overlap允许和外层MPI进程共享节点 subprocess.check_call([ 'srun', '-n', str(total_cpus), '--overlap', 'solver2', '-parallel' ]) # 所有进程同步等待OpenFOAM完成 comm.Barrier()
优势:无需手动计算CPU数,自动适配SLURM分配的资源,避免MPI嵌套冲突
方法二:调整外层MPI绑定策略,嵌套mpirun启动
修改外层启动命令,让每个Python进程仅占用1个核心,释放剩余资源给OpenFOAM:
外层启动命令改为:
mpirun -np 4 --bind-to core:1 --oversubscribe python run_solvers.py
Python脚本中主进程调用:
import subprocess from mpi4py import MPI comm = MPI.COMM_WORLD rank = comm.Get_rank() if rank == 0: total_cpus = int(os.environ.get('SLURM_NTASKS', 80)) subprocess.check_call([ 'mpirun', '-np', str(total_cpus), '--bind-to', 'none', '--oversubscribe', 'solver2', '-parallel' ]) comm.Barrier()
优势:兼容必须使用mpirun的场景,通过绑定策略避免资源竞争
方法三:按节点拆分OpenFOAM任务,分布式启动
提前用OpenFOAM的decomposePar将案例拆分为对应节点数的子任务,每个Python进程(对应1个节点)启动本地的OpenFOAM进程:
import subprocess import os from mpi4py import MPI comm = MPI.COMM_WORLD rank = comm.Get_rank() # 获取当前节点的CPU数 node_cpus = int(os.environ.get('SLURM_CPUS_ON_NODE', 20)) # 每个节点启动对应数量的OpenFOAM进程,处理本地子案例 subprocess.check_call([ 'mpirun', '-np', str(node_cpus), '--bind-to', 'none', '--oversubscribe', 'solver2', '-parallel', '-case', f'./case_decomposed/{rank}' ]) comm.Barrier()
优势:贴合第一个工具的节点分配逻辑,避免跨节点MPI通信冲突,资源利用率更高
内容的提问来源于stack exchange,提问作者yvrob
相关产品推荐
相关产品推荐

