Slurm数组作业:如何利用全部逻辑处理器并解决单任务占2CPU问题
Slurm数组任务占用2个CPU的问题解决
问题背景
在Slurm集群上运行包含2700个任务的数组作业,节点配置为48物理核心、96逻辑核心。通过sbatch指定--ntasks=1和--cpus-per-task=1,期望每个数组任务仅占用1个逻辑CPU,从而实现96任务并行,但实际每个任务占用2个CPU,无法满负载运行。
问题重现
测试脚本:
#!/bin/bash #SBATCH --ntasks=1 #SBATCH --cpus-per-task=1 #SBATCH --array=0-199 seed=$((SLURM_ARRAY_TASK_ID % 10 + 1)) line=$((SLURM_ARRAY_TASK_ID / 10 + 1)) line=${line%%.*} file=$(sed "${line}q;d" ./instances/small.txt) output=${file#"instances/"} output=${output%".dat"} srun --output="out/${output}_${seed}.stdout.txt" ./a.out "${file}" out/ -seed "${seed}" -t 1765
scontrol show node node04输出:
NodeName=node04 Arch=x86_64 CoresPerSocket=24 CPUAlloc=8 CPUTot=96 CPULoad=1.14 AvailableFeatures=(null) ActiveFeatures=(null) Gres=gpu:3 NodeAddr=node04 NodeHostName=node04 Version=19.05.5 OS=Linux 5.4.0-196-generic #216-Ubuntu SMP Thu Aug 29 13:26:53 UTC 2024 RealMemory=515624 AllocMem=114688 FreeMem=21583 Sockets=2 Boards=1 State=MIXED ThreadsPerCore=2 TmpDisk=0 Weight=1 Owner=N/A MCS_label=N/A Partitions=networkcia BootTime=2024-09-28T15:29:38 SlurmdStartTime=2024-10-25T10:47:24 CfgTRES=cpu=96,mem=515624M,billing=96 AllocTRES=cpu=8,mem=112G CapWatts=n/a CurrentWatts=0 AveWatts=0 ExtSensorsJoules=n/s ExtSensorsWatts=0 ExtSensorsTemp=n/s
作业状态squeue输出:
JOBID PARTITION NAME USER ST TIME NODES CPUS 6304_[4 networkcia small myuser PD 0:00 1 1 6304_0 networkcia small myuser R 0:01 1 2 6304_1 networkcia small myuser R 0:01 1 2 6304_2 networkcia small myuser R 0:01 1 2 ...
原因分析
srun默认资源分配:节点开启超线程(ThreadsPerCore=2),脚本中使用srun但未明确限制CPU资源时,Slurm默认会将任务绑定到一个物理核心的两个逻辑线程,导致CPU计数为2。- 程序多线程特性:如果
a.out是多线程程序(如使用OpenMP、pthread),即使只申请1个CPU,程序会自动启动额外线程,占用更多逻辑核心。
解决方案
1. 强制srun使用1个CPU
在srun命令中明确指定CPU数量并绑定到单个逻辑线程,避免超线程占用:
srun --cpus-per-task=1 --cpu-bind=threads --output="out/${output}_${seed}.stdout.txt" ./a.out "${file}" out/ -seed "${seed}" -t 1765
或者绑定到单个核心(适合不需要超线程的场景):
srun --cpus-per-task=1 --cpu-bind=cores --output="out/${output}_${seed}.stdout.txt" ./a.out "${file}" out/ -seed "${seed}" -t 1765
2. 直接执行程序,移除srun
数组作业的每个任务本身就是独立执行环境,无需srun启动程序,直接运行./a.out即可:
修改脚本执行部分:
./a.out "${file}" out/ -seed "${seed}" -t 1765 > "out/${output}_${seed}.stdout.txt"
这样每个数组任务只会占用申请的1个CPU,可实现96任务并行。
3. 限制程序线程数
如果a.out是多线程程序,通过环境变量强制限制线程数(以OpenMP为例):
export OMP_NUM_THREADS=1 ./a.out "${file}" out/ -seed "${seed}" -t 1765 > "out/${output}_${seed}.stdout.txt"
临时解决方案(2024-10-30)
通过在每个数组任务中后台运行两个程序实例,利用被占用的2个CPU资源:
#!/bin/bash #SBATCH --ntasks=1 #SBATCH --cpus-per-task=1 #SBATCH --array=0-99 seed1=$((SLURM_ARRAY_TASK_ID % 5 * 2 + 1)) seed1=$((seed1 + 1)) line=$((SLURM_ARRAY_TASK_ID / 5 + 1)) line=${line%%.*} file=$(sed "${line}q;d" ./instances/small.txt) output=${file#"instances/"} output=${output%".dat"} ./a.out "${file}" out/ -seed "${seed1}" -t 1765 > "out/${output}_${seed1}.stdout.txt" & ./a.out "${file}" out/ -seed "${seed2}" -t 1765 > "out/${output}_${seed2}.stdout.txt" & wait
内容的提问来源于stack exchange,提问作者Rafael Martinelli
相关产品推荐
相关产品推荐

