Slurm作业脚本仅执行首个srun问题排查及解决方案咨询
问题排查与解决方案
问题背景
原本使用以下Bash脚本,循环设置不同的OMP_NUM_THREADS值运行debug程序,并将日志输出到对应目录:
for i in 0 1 2 3 4 5 do export OMP_NUM_THREADS=$((2 **i)) && ./debug > ./logs/112500/exp$1/log-$((2 **i)).txt done
为完成32次重复实证测试,编写了Slurm作业脚本,期望每个实验按顺序执行,且实验内的srun任务需依次完成后再推进到下一步。但实际运行异常:
- 32个实验能按顺序循环,但每个实验仅执行首个
srun(对应1线程配置),仅生成log-1.txt; srun间的普通echo正常输出,但srun bash -c中的echo无输出;- 后续
srun完全未执行。
对应的Slurm脚本:
#!/bin/bash #SBATCH -p cs #SBATCH -e %j.err #SBATCH --time=05:00 #SBATCH --output=slurm-%j.out #executable for I in $(seq 32); do mkdir ./logs/112500/exp$I export OMP_NUM_THREADS=1 echo "Launching command for ./logs/112500/exp$I/log-1.txt" srun --nodes=1 --ntasks=1 --cpus-per-task=1 bash -c "./debug > ./logs/112500/exp$I/log-1.txt" export OMP_NUM_THREADS=2 srun --nodes=1 --ntasks=1 --cpus-per-task=2 bash -c "./debug > ./logs/112500/exp$I/log-2.txt" export OMP_NUM_THREADS=4 srun --nodes=1 --ntasks=1 --cpus-per-task=4 bash -c "./debug > ./logs/112500/exp$I/log-4.txt" export OMP_NUM_THREADS=8 srun --nodes=1 --ntasks=1 --cpus-per-task=8 bash -c "./debug > ./logs/112500/exp$I/log-8.txt" export OMP_NUM_THREADS=16 srun --nodes=1 --ntasks=1 --cpus-per-task=16 bash -c "./debug > ./logs/112500/exp$I/log-16.txt" export OMP_NUM_THREADS=32 srun --nodes=1 --ntasks=1 --cpus-per-task=32 bash -c "./debug > ./logs/112500/exp$I/log-32.txt" done
原因分析
- 资源分配不足:Slurm作业未通过
SBATCH参数申请足够的CPU资源,默认情况下作业仅能获取少量CPU配额(通常为1核)。第一个srun占用全部可用CPU后,后续srun因无法申请到对应--cpus-per-task的资源(2/4/8/16/32核),被调度器阻塞或直接拒绝执行。 - srun阻塞特性:
srun默认是阻塞式执行,若资源不足会一直等待,而脚本未捕获错误会继续循环下一个实验,导致每个实验仅完成第一个srun。 - 环境变量传递(次要):外部设置的
OMP_NUM_THREADS虽能被srun继承,但如果debug程序未正确读取该变量,可能导致线程数不生效,但这不是后续srun未执行的直接原因。
解决方案
1. 调整SBATCH资源参数
在脚本开头添加足够的资源申请,确保作业能覆盖最大的CPU需求(32核):
#SBATCH -p cs #SBATCH -e %j.err #SBATCH --time=05:00 #SBATCH --output=slurm-%j.out # 新增资源配置:匹配最大线程数需求 #SBATCH --nodes=1 #SBATCH --ntasks=1 #SBATCH --cpus-per-task=32
2. 优化脚本结构(可选,减少重复代码)
将内部线程数循环改为嵌套结构,提升可维护性:
#!/bin/bash #SBATCH -p cs #SBATCH -e %j.err #SBATCH --time=05:00 #SBATCH --output=slurm-%j.out #SBATCH --nodes=1 #SBATCH --ntasks=1 #SBATCH --cpus-per-task=32 # 循环32次实验 for exp_idx in $(seq 32); do exp_dir="./logs/112500/exp${exp_idx}" mkdir -p "${exp_dir}" # 循环不同线程数配置 for power in 0 1 2 3 4 5; do threads=$((2 ** power)) export OMP_NUM_THREADS="${threads}" log_file="${exp_dir}/log-${threads}.txt" echo "Launching experiment ${exp_idx} with ${threads} threads -> ${log_file}" srun --nodes=1 --ntasks=1 --cpus-per-task="${threads}" \ bash -c "./debug > '${log_file}'" done done
3. 验证错误日志
检查Slurm生成的%j.err文件(%j为作业ID),确认是否存在资源不足的错误提示(如Unable to allocate resources: Insufficient CPUs),进一步定位问题。
4. 强制错误检查(可选)
在每个srun后添加错误检查,确保任务完成后再继续:
srun ... || { echo "srun failed for ${threads} threads"; exit 1; }
内容的提问来源于stack exchange,提问作者selinnilesy
相关产品推荐
相关产品推荐

