You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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
...

原因分析

  1. srun默认资源分配:节点开启超线程(ThreadsPerCore=2),脚本中使用srun但未明确限制CPU资源时,Slurm默认会将任务绑定到一个物理核心的两个逻辑线程,导致CPU计数为2。
  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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 20:55:56