Slurm使用教程

1. 什么是Slurm

Slurm是一个开源的、高度可扩展的集群管理和工作调度系统,用于Linux和Unix操作系统。Slurm最初是由Lawrence Livermore National Laboratory开发的,现在由Slurm工作组维护。Slurm的设计目标是在大型Linux集群上提供一个可扩展的、高性能的、可靠的集群管理器。

Slurm的功能包括:

  • 分配和管理计算资源(计算节点);

  • 分配和管理任务(作业);

  • 监控系统状态;

  • 收集和报告作业资源使用情况;

  • 提供计算资源的可视化界面。

2. Slurm的使用

  • 集群常用概念

    • Resource:资源,作业运行过程中使用的可量化实体,包括硬件资源(节点、内存、CPU、GPU)和软件资源(License)

    • Cluster:集群,包含计算、存储、网络等各种资源实体且彼此联系的资源集合,物理上一般由计算处理、互联通信、I/O存储、操作系统、编译器、运行环境、开发工具等多个软硬件子系统组成。

    • Node:节点,是集群的基本组成单位,从角色上一半可以划分为管理节点、登录节点、计算节点、存储节点等。

    • job:作业,物理构成,一组关联的资源分配请求,以及一组关联的处理过程。按交互方式,可以分为交互式作业和非交互式作业;按资源使用,可以分为串行作业和并行作业。

    • queue:队列,带名称的作业容器,用户访问控制,资源使用限制。

    • Job Schedule System:作业调度系统,负责监控和管理集群中资源和作业的软件系统。

    • job step:作业步,单个作业可以有多个作业步。

    • partition:分区,根据用户的权限,作业需要被提交到特定的分区中运行。

    • tasks:任务数,默认一个任务使用一个CPU核,可理解为job需要的CPU核数。

  • Slurm常用基本命令

    • sbatch: 用于提交作业

    • squeue: 用于查看作业

    • scancel: 用于取消作业

    • sinfo: 用于查看集群状态

    • scontrol: 用于控制作业

    • sacct: 用于查看作业的详细信息

    • sreport: 用于生成报告

    • salloc:为实时处理的作业分配资源:典型场景为分配资源并启动一个shell,然后用此shell执行srun命令去执行并行任务。

    • srun:交互式运行并行作业,一般用于短时间测试。

3. Slurm的使用案例

3.1 作业提交

  • slurm 有三种模式提交作业,分别为 交互模式srun批处理模式sbatch分配模式,这三种方式只是作业提交方式的区别,在管理、调度、机时计算同等对待。一般使用批处理模式。

3.1.1 作业提交的基本格式

sbatch [options] <jobscript>

3.1.2 作业提交的常用选项

  • -A, –account=name

  • -c, –cpus-per-task=ncpus

  • -J, –job-name=name

  • -N, –nodes=nodes

  • -n, –ntasks=ntasks

  • -o, –output=name

  • -p, –partition=name

  • -t, –time=time

  • -w, –nodelist=node_list

  • -x, –exclude=node_list

  • -C, –constraint=name

  • -D, –dependency=type:jobid[:jobid…]

3.1.3 作业提交的示例

sbatch -A account_name -p partition_name -n 1 -c 1 -t 1-00:00:00 -J job_name -o job_name.out job_script.sh

批处理模式的作业提交示例:

  • 批处理模式是指用户编写作业脚本,指定作业需要的资源,提交后台执行作业

  • 作业提交后进入调度状态,在资源满足要求时,分配计算节点

  • 分配到计算资源后,自动在计算节点执行用户所编辑的脚本内的命令,sbatch 命令提交作业,终端断开连接作业依然在后台运行束,直到脚本执行结束作业自动退出 (或者在作业运行时执行 scancel 命令取消作业后作业自动停止)

  • 批处理作业的脚本为一个bash或sh文本文件

  • 计算开始后,工作目录中会生成以slurm-作业号.out文件,为作业的输出

  • 常见资源需求参数,使用SBATCH -xx xxx写入作业脚本中:

-N, --nodes=N                   #指定节点数量
-o, --output=out_filename       #指定输出文件输出
-p, --partion=debug             #指定分区
-t, --time=dd-hh:mm:ss          #作业最大运行时间--mem:指定每个节点上使用的物理内存
--begin:指定作业开始时间
-D,--chdir:指定脚本/命令的工作目录
-c, --cpu-per-task=NCPUs        #指定每个进程使用核数,不指定默认为1
-e, --error=error_filename      #指定错误文件输出
-J, --job-name=JOBNAME          #指定作业名称
--mail-type=END/FAIL/ALL        #邮件提醒,可选:END,FAIL,ALL
--mail-user=mail_address        #通知邮箱地址
-n, --ntask=NTASKs #指定总进程数;不使用cpus-per-task,可理解为进程数即为核数
--ntask-per-node=N #指定每个节点进程数/核数,使用-n参数后变为每个节点最多运行的进程数-w, --nodelist=node[1,2]        #指定优先使用节点,不可与避免节点冲突
-x, --exclude=node[3,5-6]       #指定避免使用节点,不可与优先节点冲突
--mem-per-cpu=MB                #指定计算cpu最大占用内存大小

示例文件:

#!/bin/bash
#提交单个作业
#SBATCH --job-name=JOBNAME      %指定作业名称
#SBATCH --partition=debug       %指定分区
#SBATCH --nodes=2               %指定节点数量
#SBATCH --cpus-per-task=1       %指定每个进程使用核数,不指定默认为1
#SBATCH -n 32       %指定总进程数;不使用cpus-per-task,可理解为进程数即为核数
#SBATCH --ntasks-per-node=16    %指定每个节点进程数/核数,使用-n参数(优先级更高),变为每个节点最多运行的任务数#SBATCH --time=240:00:00      %作业最大运行时长,参考格式填写
#SBATCH --output=file_name      %指定输出文件输出
#SBATCH --error=file_name       %指定错误文件输出
#SBATCH --mail-type=ALL         %邮件提醒,可选:END,FAIL,ALL
#SBATCH --mail-user=address     %通知邮箱地址module load apps/anaconda3/2021.05  # 加载anaconda
source activate torch1.8.1  # 加载anaconda虚拟环境python main.py --no_static=True --model=lstm --seed=100 train_basins  # 执行python脚本

命令行输入 sbatch 作业脚本名提交作业

3.2 作业查看

3.2.1 作业查看的基本格式

squeue [options]

3.2.2 作业查看的常用选项

  • -a, –all

  • -A, –account=name

  • -j, –job=job_id

  • -n, –name=name

  • -o, –format=format

  • -p, –partition=name

  • -P, –detailed

  • -r, –noconvert

  • -s, –states=list

  • -t, –states=list

  • -u, –user=list

  • -h, –help

显示占用核心数:

alias squeue='squeue -o "%.8i   %.7P   %.25j   %.4u   %.2t   %.11M   %.4D   %.16R   %.4C"'

3.2.3 作业查看的示例

squeue -u user_name
# 例如
squeue -u host

3.3 作业取消

3.3.1 作业取消的基本格式

scancel [options] <job_id>

3.3.2 作业取消的常用选项

  • -a, –all

  • -b, –batch

  • -h, –help

  • -i, –interactive

  • -n, –name=name

  • -p, –partition=name

  • -u, –user=name

3.3.3 作业取消的示例

scancel job_id

3.4 集群状态查看

3.4.1 集群状态查看的基本格式

sinfo [options]

3.4.2 集群状态查看的常用选项

  • -a, –all

  • -h, –help

  • -l, –long

  • -o, –format=format

  • -p, –partition=name

  • -R, –resv

  • -t, –states=list

  • -u, –user=list

3.4.3 集群状态查看的示例

sinfo -l

3.5 作业控制

3.5.1 作业控制的基本格式

scontrol [options] <command>

3.5.2 作业控制的常用选项

  • -a, –all

  • -b, –batch

  • -d, –details

  • -h, –help

  • -i, –interactive

  • -l, –long

  • -o, –format=format

  • -p, –partition=name

  • -t, –states=list

  • -u, –user=list

作业信息查看

scontrol show job JOBID         #查看作业的详细信息
scontrol show node              #查看所有节点详细信息
scontrol show node node-name    #查看指定节点详细信息
scontrol show node | grep CPU   #查看各节点cpu状态
scontrol show node node-name | grep CPU #查看指定节点cpu状态

更新作业信息

作业提交后,但相关作业属性错误,取消任务修改作业后需要重新排队,在作业运行开始前可以使用scontrol更新作业的运行属性。

scontrol update jobid=JOBID ATTRIBUTE=INFO # ATTRIBUTE为下列属性名,INFO修改的属性值
partition=`<name>`
name=`<name>`
numcpus=<min_count-max_count>
numnodes=<min_count-max_count>
numtasks=`<count>`
reqnodelist=`<nodes>`
reqcores=`<count>`
nodelist=`<nodes>`
excnodelist=`<nodes>`
starttime=yyyy-mm-dd
timelimit=d-hⓂ️s
mincpusnode=`<count>`
minmemorycpu=`<megabytes>`
minmemorynode=`<megabytes>`

3.5.3 作业控制的示例

#显示作业ID
scontrol show job job_id
# 修改作业依赖
scontrol update jobid=1295 dependency=afterok:1317
# 修改任务占用CPU数
scontrol update jobid=1295 numcpus=8
#终止作业
scancel JOBID  # 终止作业
#将作业放在其队列的顶部
scontrol top <job-id>

3.6 作业详细信息查看

3.6.1 作业详细信息查看的基本格式

sacct [options]

3.6.2 作业详细信息查看的常用选项

  • -a, –allusers

  • -A, –account=name

  • -b, –starttime=time

  • -c, –clusters=cluster_list

  • -d, –duplicates

  • -D, –dformat=format

  • -e, –endtime=time

  • -h, –help

  • -j, –jobs=job_list

  • -l, –long

  • -M, –mail

  • -n, –name=name

  • -o, –format=format

  • -p, –parsable2

  • -P, –noconvert

  • -r, –reverse

  • -S, –noheader

  • -t, –state=state_list

  • -u, –user=user_list

  • -V, –version

  • -w, –wide

3.6.3 作业详细信息查看的示例

sacct -j job_id

3.7 作业报告生成

3.7.1 作业报告生成的基本格式

sreport [options] <report> <cluster> [start] [end]

3.7.2 作业报告生成的常用选项

  • -a, –all

  • -A, –account=name

  • -b, –starttime=time

  • -c, –clusters=cluster_list

  • -d, –duplicates

  • -D, –dformat=format

  • -e, –endtime=time

  • -h, –help

  • -j, –jobs=job_list

  • -l, –long

  • -M, –mail

  • -n, –name=name

  • -o, –format=format

  • -p, –parsable2

  • -P, –noconvert

  • -r, –reverse

  • -S, –noheader

  • -t, –state=state_list

  • -u, –user=user_list

  • -V, –version

  • -w, –wide

3.7.3 作业报告生成的示例

sreport cluster AccountUtilizationByUser cluster_name start_time end_time

4. Slurm的配置

4.1 配置文件

  • slurm.conf:Slurm的主配置文件,包含了Slurm的所有配置信息

4.2 配置文件的位置

/etc/slurm/slurm.conf

5. Slurm的常见问题

5.1 作业提交失败

5.1.1 问题描述

sbatch: error: Batch job submission failed: Socket timed out on send/recv operation

5.1.2 问题原因

  • 作业提交的节点与控制节点之间的网络不通

5.1.3 问题解决

  • 检查作业提交的节点与控制节点之间的网络是否通畅

5.2 作业运行失败

5.2.1 问题描述

srun: error: Unable to create step for job 123456: Socket timed out on send/recv operation

5.2.2 问题原因

  • 作业运行的节点与控制节点之间的网络不通

5.2.3 问题解决

  • 检查作业运行的节点与控制节点之间的网络是否通畅

6. 重启Slurm

  • 重启Slurm的基本格式

systemctl restart slurmctld

7. 查看Slurm的版本

scontrol --version

8. Slurm的状态为down的解决方案

  • 如果节点状态为down,可以使用如下命令将节点状态设置为resume

(base) [root@node02 ~]# scontrol update node=node02 state=down reason=hung
(base) [root@node02 ~]# scontrol update node=node02 state=resume
[host@node01 ~]$ sinfo
PARTITION AVAIL  TIMELIMIT  NODES  STATE NODELIST
debug01*     up   infinite      3   idle node[01-03]

[host@node01 ~]$ pbsnodes -a

.. code-block:: sh
    :caption: sinfo
    :name: test333
    :emphasize-lines: 2
    :linenos:
  
    node01
        state = free
        np = 128
        ntype = cluster
        status = rectime=1686038364,state=free,slurmstate=idle,size=0kb:0kb,ncpus=128,boards=1,sockets=2,cores=64,threads=1,availmem=1mb,opsys=linux 3.10.0-1127.el7.x86_64 #1 smp tue mar 31 23:36:51 utc 2020,arch=x86_64

    node02
        state = free
        np = 56
        ntype = cluster
        status = rectime=1686038364,state=free,slurmstate=idle,size=0kb:0kb,ncpus=56,boards=1,sockets=2,cores=28,threads=1,availmem=1mb,opsys=linux 3.10.0-1127.el7.x86_64 #1 smp tue mar 31 23:36:51 utc 2020,arch=x86_64

    node03
        state = free
        np = 40
        ntype = cluster
        status = rectime=1686038364,state=free,slurmstate=idle,size=0kb:0kb,ncpus=40,boards=1,sockets=2,cores=20,threads=1,availmem=1mb,opsys=linux 3.10.0-1127.el7.x86_64 #1 smp tue mar 31 23:36:51 utc 2020,arch=x86_64
(base) [root@master ~]# scontrol show node
NodeName=master CoresPerSocket=6
   CPUAlloc=0 CPUEfctv=6 CPUTot=6 CPULoad=N/A
   AvailableFeatures=(null)
   ActiveFeatures=(null)
   Gres=(null)
   NodeAddr=master NodeHostName=master
   RealMemory=1 AllocMem=0 FreeMem=N/A Sockets=1 Boards=1
   State=IDLE+NOT_RESPONDING ThreadsPerCore=1 TmpDisk=0 Weight=1 Owner=N/A MCS_label=N/A
   Partitions=hpc
   BootTime=None SlurmdStartTime=None
   LastBusyTime=2023-07-05T21:51:27
   CfgTRES=cpu=6,mem=1M,billing=6
   AllocTRES=
   CapWatts=n/a
   CurrentWatts=0 AveWatts=0
   ExtSensorsJoules=n/s ExtSensorsWatts=0 ExtSensorsTemp=n/s

NodeName=node01 Arch=x86_64 CoresPerSocket=4
   CPUAlloc=0 CPUEfctv=4 CPUTot=4 CPULoad=0.04
   AvailableFeatures=(null)
   ActiveFeatures=(null)
   Gres=(null)
   NodeAddr=node01 NodeHostName=node01 Version=22.05.5
   OS=Linux 3.10.0-1160.92.1.el7.x86_64 #1 SMP Tue Jun 20 11:48:01 UTC 2023
   RealMemory=1 AllocMem=0 FreeMem=6558 Sockets=1 Boards=1
   State=IDLE ThreadsPerCore=1 TmpDisk=0 Weight=1 Owner=N/A MCS_label=N/A
   Partitions=hpc
   BootTime=2023-07-05T21:27:14 SlurmdStartTime=2023-07-05T21:50:00
   LastBusyTime=2023-07-05T21:51:51
   CfgTRES=cpu=4,mem=1M,billing=4
   AllocTRES=
   CapWatts=n/a
   CurrentWatts=0 AveWatts=0
   ExtSensorsJoules=n/s ExtSensorsWatts=0 ExtSensorsTemp=n/s