如何在Slurm集群中突破作业提交限额批量运行串行作业?
问题
在Slurm管理的HPC集群上需要并行运行大量独立串行作业,但用户提交作业的限额是最多100个,当前脚本只能同时处理100个作业,希望找到更优方案,将整个模拟任务作为单个大作业提交。当前使用的批量提交脚本如下:
#!/bin/bash max_jobs=100 # Set the directory where the simulation folders are located dir="/work/parameter_study/" # Loop over the parameter cases for param_case in {0001..0216}_sim; do cd $dir/$param_case # Loop over the Monte Carlo simulations for mcs_case in {0001..1500}_MCS; do cd $dir/$param_case/$mcs_case #sed -i -e 's/\r$//' a.out chmod 777 a.out # Check if max_jobs is exceeded while true do # Count rows without header job_count=$(squeue -h -t PD,R | wc -l) if [ $job_count -lt $max_jobs ] then break fi sleep 0.5 done # Submit a job for each simulation using the a.out file jobID=$(sbatch -p single -J ${param_case}_${msc_case} --wrap ./a.out) echo "${jobID} ${param_case} ${mcs_case} - $(date '+%H:%M:%S')" done done # Wait for all jobs to finish wait
最优方案:使用Slurm作业数组(Job Arrays)
这是Slurm原生支持的批量处理独立任务的方式,只需要提交一个作业就能管理所有任务,完全不占多个作业名额,刚好避开100个作业的限制,是最适合你的方案。
先生成任务列表文件
把所有要运行的任务的工作目录整理成一个文本文件,每个目录占一行:
#!/bin/bash dir="/work/parameter_study/" # 创建并清空任务列表文件 > task_list.txt for param_case in {0001..0216}_sim; do for mcs_case in {0001..1500}_MCS; do echo "$dir/$param_case/$mcs_case" >> task_list.txt done done
编写作业数组脚本并提交
写一个名为array_job.sh的脚本,用Slurm的数组索引读取任务列表里的路径:
#!/bin/bash #SBATCH -p single #SBATCH -J parameter_study_array #SBATCH --array=1-$(wc -l < task_list.txt) # 数组范围对应任务列表的总行数 #SBATCH --ntasks=1 #SBATCH --cpus-per-task=1 # 获取当前数组任务对应的工作目录 WORK_DIR=$(sed -n "${SLURM_ARRAY_TASK_ID}p" task_list.txt) # 进入目录运行程序 cd $WORK_DIR chmod 777 a.out ./a.out
提交这个作业即可:
sbatch array_job.sh
整个任务只占1个作业名额,Slurm会自动调度所有数组任务,并行运行的数量取决于集群可用资源和队列配置。你可以用sacct或者squeue -u $USER查看所有数组任务的状态。
备选方案:单个作业内用GNU Parallel + srun
如果你的集群安装了GNU Parallel,也可以在单个作业里启动多个并行任务,用srun分配资源:
编写并行作业脚本parallel_job.sh
#!/bin/bash #SBATCH -p single #SBATCH -J parameter_study_parallel #SBATCH --ntasks=100 # 设置同时运行的任务数,别超过队列允许的资源上限 #SBATCH --cpus-per-task=1 dir="/work/parameter_study/" # 生成所有要执行的命令 generate_tasks() { for param_case in {0001..0216}_sim; do for mcs_case in {0001..1500}_MCS; do echo "cd $dir/$param_case/$mcs_case && chmod 777 a.out && ./a.out" done done } # 用GNU Parallel把任务分发给srun执行 generate_tasks | parallel --jobs $SLURM_NTASKS srun --exclusive --ntasks=1 {}
提交作业:
sbatch parallel_job.sh
这个方案同样只占1个作业名额,--ntasks设置你想要同时运行的任务数,GNU Parallel会自动将任务分配给每个srun进程。
方案对比
- 作业数组:Slurm原生支持,管理简单,任务状态一目了然,适合大规模任务,优先选择。
- GNU Parallel + srun:灵活性更高,适合需要自定义调度逻辑的场景,但前提是集群已安装GNU Parallel。
内容的提问来源于stack exchange,提问作者Sebastian Krug
相关产品推荐
相关产品推荐

