跳转至

批处理方式提交作业:sbatch

Slurm支持利用sbatch命令采用批处理方式运行作业,sbatch命令在脚本正确传递给作业调度系统后立即退出,同时获取到一个作业号。作业等所需资源满足后开始运行。

sbatch提交一个批处理作业脚本到Slurm。批处理脚本名可以在命令行上通过传递给sbatch,如没有指定文件名,则sbatch从标准输入中获取脚本内容。

脚本文件基本格式:

  • 第一行以#!/bin/sh等指定该脚本的解释程序,/bin/sh可以变为/bin/bash、/bin/csh等。
  • 在可执行命令之前的每行“#SBATCH”前缀后跟的参数作为作业调度系统参数。在任何非注释及空白之后的“#SBATCH”将不再作为Slurm参数处理。

默认,标准输出和标准出错都定向到同一个文件slurm-%j.out,“%j”将被作业号代替。

脚本myscript内容:

#!/bin/sh
#SBATCH --time=1
#SBATCH -p serial
srun hostname |sort

采用4个节点(-N4)运行:sbatch -p batch -N4 myscript

在这里,虽然脚本中利用“#SBATCH -p serial”指定了使用serial队列,但命令行中的-p batch优先级更高,因此实际提交到batch队列。

提交成功后有类似输出:

salloc: Granted job allocation 65537

其中65537为分配的作业号。

程序结束后的作业日志文件slurm-65537.out显示:

node1
node2
node3
node4

从标准输入获取脚本内容,可采用以下两种方式之一:

  1. 运行sbatch -N4,显示等待后输入:
#!/bin/sh
srun hostname |sort

输入以上内容后按CTRL+D终止输入。

  1. 运行sbatch -N4 <<EOF
> #!/bin/sh
> srun hostname | sort
> EOF

  -  第一个EOF表示输入内容的开始标识符

  -  最后的EOF表示输入内容的终止标识符,在两个EOF之间的内容为实际执行的内容。

  -  >实际上是每行输入回车后自动在下一行出现的提示符。

以上两种方式输入结束后将显示:

sbatch: Submitted batch job 65541

常见主要选项参见提交作业命令共同说明

sbatch主要输入环境变量

一些选项可通过环境变量来设置,命令行的选项优先级高于设置的环境变量,将覆盖掉环境变量的设置。环境变量与对应的参数如下:

  • SBATCH_ACCOUNT:类似-A、--account。
  • SBATCH_ACCTG_FREQ:类似--acctg-freq。
  • SBATCH_ARRAY_INX:类似-a、--array。
  • SBATCH_BATCH:类似--batch。
  • SBATCH_CLUSTERS 或 SLURM_CLUSTERS:类似--clusters。
  • SBATCH_CONSTRAINT:类似-C, --constraint。
  • SBATCH_CORE_SPEC:类似--core-spec。
  • SBATCH_CPUS_PER_GPU:类似--cpus-per-gpu。
  • SBATCH_DEBUG:类似-v、--verbose。
  • SBATCH_DISTRIBUTION:类似-m、--distribution。
  • SBATCH_EXCLUSIVE:类似--exclusive。
  • SBATCH_EXPORT:类似--export。
  • SBATCH_GEOMETRY:类似-g、--geometry。
  • SBATCH_GET_USER_ENV:类似--get-user-env。
  • SBATCH_GPUS:类似 -G, --gpus。
  • SBATCH_GPU_BIND:类似 --gpu-bind。
  • SBATCH_GPU_FREQ:类似 --gpu-freq。
  • SBATCH_GPUS_PER_NODE:类似 --gpus-per-node。
  • SBATCH_GPUS_PER_TASK:类似 --gpus-per-task。
  • SBATCH_GRES:类似 --gres。
  • SBATCH_GRES_FLAGS:类似--gres-flags。
  • SBATCH_HINT 或 SLURM_HINT:类似--hint。
  • SBATCH_IGNORE_PBS:类似--ignore-pbs。
  • SBATCH_JOB_NAME:类似-J、--job-name。
  • SBATCH_MEM_BIND:类似--mem-bind。
  • SBATCH_MEM_PER_CPU:类似--mem-per-cpu。
  • SBATCH_MEM_PER_GPU:类似--mem-per-gpu。
  • SBATCH_MEM_PER_NODE:类似--mem。
  • SBATCH_NETWORK:类似--network。
  • SBATCH_NO_KILL:类似-k, –no-kill。
  • SBATCH_NO_REQUEUE:类似--no-requeue。
  • SBATCH_OPEN_MODE:类似--open-mode。
  • SBATCH_OVERCOMMIT:类似-O、--overcommit。
  • SBATCH_PARTITION:类似-p、--partition。
  • SBATCH_PROFILE:类似--profile。
  • SBATCH_QOS:类似--qos。
  • SBATCH_RAMDISK_IMAGE:类似--ramdisk-image。
  • SBATCH_RESERVATION:类似--reservation。
  • SBATCH_REQUEUE:类似--requeue。
  • SBATCH_SIGNAL:类似--signal。
  • SBATCH_THREAD_SPEC:类似--thread-spec。
  • SBATCH_TIMELIMIT:类似-t、--time。
  • SBATCH_USE_MIN_NODES:类似--use-min-nodes。
  • SBATCH_WAIT:类似-W、--wait。
  • SBATCH_WAIT_ALL_NODES:类似--wait-all-nodes。
  • SBATCH_WAIT4SWITCH:需要交换的最大时间,参见See--switches。
  • SLURM_EXIT_ERROR:设定Slurm出错时的退出码。
  • SLURM_STEP_KILLED_MSG_NODE_ID=ID:如果设置,当作业或作业步被信号终止时,只有指定ID的节点记录。

sbatch主要输出环境变量

Slurm将在作业脚本中输出以下变量,作业脚本可以使用这些变量:

  • SBATCH_MEM_BIND:--mem-bind选项设定。
  • SBATCH_MEM_BIND_VERBOSE:如--mem-bind选项包含verbose选项时,则由其设定。
  • SBATCH_MEM_BIND_LIST:内存绑定时设定的bit掩码。
  • SBATCH_MEM_BIND_PREFER:--mem-bin prefer优先权。
  • SBATCH_MEM_BIND_TYPE:由--mem-bind选项设定。
  • SLURM_ARRAY_TASK_ID:作业组ID(索引)号。
  • SLURM_ARRAY_TASK_MAX:作业组最大ID号。
  • SLURM_ARRAY_TASK_MIN:作业组最小ID号。
  • SLURM_ARRAY_TASK_STEP:作业组索引步进间隔。
  • SLURM_ARRAY_JOB_ID:作业组主作业号。
  • SLURM_CLUSTER_NAME:集群名。
  • SLURM_CPUS_ON_NODE:分配的节点上的CPU颗数。
  • SLURM_CPUS_PER_GPU:每个任务的CPU颗数,只有--cpus-per-gpu选项设定时才有。
  • SLURM_CPUS_PER_TASK:每个任务的CPU颗数,只有--cpus-per-task选项设定时才有。
  • SLURM_DISTRIBUTION:类似-m, --distribution。
  • SLURM_EXPORT_ENV:类似-e, --export。
  • SLURM_GPU_BIND:指定绑定任务到GPU,仅提交时具有--gpu-bind参数时。
  • SLURM_GPU_FREQ:需求的GPU频率,仅提交时具有--gpu-freq参数时。
  • SLURM_GPUS Number of GPUs requested. Only set if the -G, --gpus option is specified.
  • SLURM_GPU_BIND:需要的任务绑定到GPU,仅提交时有–gpu-bind参数时。
  • SLURM_GPUS_PER_NODE:需要的每个节点的GPU颗数,仅提交时具有--gpus-per-node参数时。
  • SLURM_GPUS_PER_SOCKET:需要的每个socket的GPU颗数,仅提交时具有--gpus-per-socket参数时。
  • SLURM_GPUS_PER_TASK:需要的每个任务的GPU颗数,仅提交时具有--gpus-per-task参数时。
  • SLURM_GTIDS:在此节点上运行的全局任务号。以0开始,逗号,分隔。
  • SLURM_JOB_ACCOUNT:作业的记账账户名。
  • SLURM_JOB_ID:作业号。
  • SLURM_JOB_CPUS_PER_NODE:每个节点上的CPU颗数,格式类似40(x3),3,顺序对应SLURM_JOB_NODELIST节点名顺序。
  • SLURM_JOB_DEPENDENCY:作业依赖信息,由--dependency选项设置。
  • SLURM_JOB_NAME:作业名。
  • SLURM_JOB_NODELIST:分配的节点名列表,格式类似node[1-10,11,13-28]。
  • SLURM_JOB_NUM_NODES:分配的节点总数。
  • SLURM_JOB_PARTITION:使用的队列名。
  • SLURM_JOB_QOS:需要的服务质量(QOS)。
  • SLURM_JOB_RESERVATION:作业预留。
  • SLURM_LOCALID:节点本地任务号。
  • SLURM_MEM_PER_CPU:类似--mem-per-cpu,每颗CPU需要的内存。
  • SLURM_MEM_PER_GPU:类似--mem-per-gpu,每颗GPU需要的内存。
  • SLURM_MEM_PER_NODE:类似--mem,每个节点的内存。
  • SLURM_NODE_ALIASES:分配的节点名、通信IP地址和主机名组合,类似 SLURM_NODE_ALIASES=ec0:1.2.3.4:foo,ec1:1.2.3.5:bar。
  • SLURM_NODEID:分配的节点号。
  • SLURM_NTASKS:类似-n, --ntasks,总任务数,CPU核数。
  • SLURM_NTASKS_PER_CORE:每个CPU核分配的任务数。
  • SLURM_NTASKS_PER_NODE:每个节点上的任务数 。
  • SLURM_NTASKS_PER_SOCKET:每颗CPU上的任务数,仅--ntasks-per-socket选项设定时设定。
  • SLURM_PRIO_PROCESS:进程的调度优先级(nice值)。
  • SLURM_PROCID:当前进程的MPI秩。
  • SLURM_PROFILE:类似--profile。
  • SLURM_RESTART_COUNT:因为系统失效等导致的重启次数。
  • SLURM_SUBMIT_DIR:sbatch启动目录,即提交作业时目录,或提交时由-D, --chdir参数指定的。
  • SLURM_SUBMIT_HOST:sbatch启动的节点名,即提交作业时节点。
  • SLURM_TASKS_PER_NODE:每节点上的任务数,以SLURM_NODELIST中的节点顺序显示,以,分隔。如果两个或多个连续节点上的任务数相同,数后跟着(x#),其中#是对应的节点数,如“SLURM_TASKS_PER_NODE=2(x3),1”表示前三个节点上的作业数为3,第四个节点上的任务数为1。
  • SLURM_TASK_PID:任务的进程号PID。
  • SLURMD_NODENAME:执行作业脚本的节点名。

串行作业提交

对于串行程序,用户可类似下面两者之一:

  1. 直接采用sbatch -n1 -o job-%j.log -e job-%j.err yourprog方式运行
  2. 编写命名为serial_job.sh(此脚本名可以按照用户喜好命名)的串行作业脚本,其内容如下:
serial_job.sh
#!/bin/sh
#SBATCH -N 1
#SBATCH -J job_name
#SBATCH -p [partition]
#SBATCH -A [account]
#SBATCH -q [QOS]
#SBATCH -o job-%j.log
#SBATCH -e job-%j.err

echo Running on hosts
echo Time is `date`
echo Directory is $PWD
echo This job runs on the following nodes:
echo $SLURM_JOB_NODELIST

module load intel/2023.2

echo This job has allocated 1 cpu core.

./yourprog

注意请替换队列 (partiton)、账户 (account) 和服务质量 (QOS) 为实际情况。以下不再赘述。

必要时需在脚本文件中利用module命令设置所需的环境,如上面的module load intel/2023.2

作业脚本编写完成后,可以按照下面命令提交作业:

sbatch serial_job.sh

OpenMP共享内存并行作业提交

对于OpenMP共享内存并行程序,可编写命名为omp_job.sh的作业脚本,内容如下:

#!/bin/sh
#SBATCH -J job_name
#SBATCH -p [partition]
#SBATCH -A [account]
#SBATCH -q [QOS]
#SBATCH -o job-%j.log
#SBATCH -e job-%j.err
#SBATCH -N 1
#SBATCH -n 1
#SBATCH -c 8

echo Running on hosts
echo Time is `date`
echo Directory is $PWD
echo This job runs on the following nodes:
echo $SLURM_JOB_NODELIST

module load intel/2016.3.210
echo This job has allocated 1 cpu core.
export OMP_NUM_THREADS=8
./yourprog

相对于串行作业脚本,主要增加export OMP_NUM_THREADS=8#SBATCH -N 1 -n 1 -c 8,表示使用一个节点内部的八个核,从而保证是在同一个节点内部,需几个核就设置 -c 为几。-c 后跟的不能超过单节点内CPU核数。

作业脚本编写完成后,可以按照下面命令提交作业:

sbatch omp_job.sh

MPI并行作业提交

与串行作业类似,对于MPI并行作业,则需编写类似下面脚本mpi_job.sh

#!/bin/sh
#SBATCH -J job_name
#SBATCH -p [partition]
#SBATCH -A [account]
#SBATCH -q [QOS]
#SBATCH -o job-%j.log
#SBATCH -e job-%j.err
#SBATCH -N 1 -n 8

echo Time is `date`
echo Directory is $PWD
echo This job runs on the following nodes:
echo $SLURM_JOB_NODELIST
echo This job has allocated $SLURM_JOB_CPUS_PER_NODE cpu cores.

module load intel/2023.2
mpirun ./yourprog

与串行程序的脚本相比,主要不同之处在于需采用mpirun或mpiexec的命令格式提交并行可执行程序。采用不同MPI提交时,需要打开上述对应的选项。

总共需要使用多少个核,则设置 -n 为多少。

需要跨节点并行时,也可以将 #SBATCH -N <nodes> -n <nprocs> 替换为:

#SBATCH -N <nodes>
#SBATCH --ntasks-per-node=<nprocs-per-node>

即定义每个节点使用多少个核,根据申请的资源总量由 Slurm 进行分配。

与串行作业类似,可使用下面方式提交:

sbatch mpi_job.sh

GPU作业提交

运行GPU作业,需要提交时利用 --gres=gpu 等指明需要的GPU资源并用 -p 指明采用等GPU队列。

脚本gpu_job.sh内容:

#!/bin/sh
#An example for gpu job.
#SBATCH -J job_name
#SBATCH -p gpu
#SBATCH -A [account]
#SBATCH -q [QOS]
#SBATCH -o job-%j.log
#SBATCH -e job-%j.err
#SBATCH -N 1 -n 8 --gres=gpu:2
./your-gpu-prog

上面 -p gpu 指定采用GPU队列,--gres=gpu:2 指明每个节点使用 2 块NVIDIA A100 GPU卡。

Tip

目前嘉庚智算上的 GPU 均为 NVIDIA A100 80G NVLink 全连接计算卡。

作业获取的节点名及对应CPU核数解析

作业调度系统主要负责分配节点及该节点分配的CPU核数等,在Slurm作业脚本中利用环境变量可以获取分配到的节点名(SLURM_JOB_NODELIST及对应核数(SLURM_JOB_CPUS_PER_NODE)或对应的任务数(SLURM_TASKS_PER_NODE),然后根据自己程序原始的命令在Slurm脚本中进行修改就成。

SLURM_JOB_NODELISTSLURM_TASKS_PER_NODE有一定的格式,以下为一个参考解析脚本,可以在自己的Slurm脚本中参考获取自己的节点等信息。

上面只是例子,要加在自己的Slurm脚本中,而不是先提交上面这个脚本获取节点名后放到slurm脚本中,其原因在于除非提交时指定节点名,否则每次提交后获取的节点名等是有可能变的。比如针对star-cmm+软件,原来的方式是:

/STATCMM+PATH/bin/starccm+ -rsh ssh -batch -power -on cnode400:40,cnode432:40 FireAndSmokeResampled.sim >residual.log

则可以改为下面脚本:

#!/bin/bash
#Auther HM_Li<hmli@ustc.edu.cn>
#SLURM_JOB_NODELIST=cnode[001-003,005,440-441]
BASENAME=${SLURM_JOB_NODELIST%[*}
LIST=${SLURM_JOB_NODELIST#*[}
LIST=${LIST%]}
IDLIST=''
for i in `echo $LIST | tr ',' ' '`
do
   if [[ $i =~ '-' ]]; then
      IDLIST=$IDLIST' '`seq -w `echo $i | tr '-' ' '``
   else
      IDLIST=$IDLIST' '$i
   fi
done
NODELIST=''
for i in $IDLIST
do
    NODELIST=$NODELIST" $BASENAME"$i
done
echo -e "Node list: \n\t"$NODELIST

#SLURM_TASKS_PER_NODE='40(x3),23,20(x2)'
#SLURM_JOB_CPUS_PER_NODE='40(x3),23,20(x2)'
CORELIST=''
for i in `echo $SLURM_JOB_CUPS_PER_NODE| tr ',' ' '`
do
  if [[ $i =~ 'x' ]]; then
     read CORES NODES <<<`echo $i| tr '(x)' ' '`
     for n in `seq 1 $NODES`
     do
         CORELIST=$CORELIST' '$CORES
     done
  else
     CORELIST=$CORELIST' '$i
  fi
done
echo -e "\nCPU Core list: \n\t$CORELIST"

echo -e "\nNode list with corresponding CPU Cores: "
CARR=(${CORELIST})
i=0
for n in $NODELIST
  do
    echo -e "\t"$n: ${CARR[$i]}
    i=$(($i+1))
 done