Linux【9】-进程管理7-集群管理--slurm

不开心呀,sge都没搞通,现在就要开始撸slurm了。没办法,谁叫我们要遇到问题,解决问题呢

一、概述

Slurm 是一个开源、容错、高可伸缩的集群管理和大型小型 Linux 集群作业调度系统。slurm不需要对操作系统内核进行修改,而是相对独立的。 作为集群工作负载管理器。slurm有三个关键功能:

  1. 首先,它在一段时间内为用户分配独占或者非独占的计算资源,以便他们能够执行工作任务
  2. 其次,它能提供一个框架,用于在分配的节点集上启动,执行,监视工作,通常是并行作业任务
  3. 最后,它通过管理挂起的工作队列,来仲裁资源争夺问题

构架

如下图所示,slurm构成有:

  1. 运行在每个计算节点上的slurmd守护进程
  2. 运行在管理节点上的中央slurmctld守护进程(可选的故障切换节点模式)

用户命令,包括:sacct,salloc,sattach,sbatch,sbcast,scancel,scontrol,sinfo,smap,squeue,srun,strigger,sviw,sreport等,均可以在集群的任何地方运行。

如下图所示,由这些 Slurm 守护程序管理的实体,包括:

  • 计算资源node
  • 计算资源组成的逻辑集partition
  • 分配给用户指定的时间量的资源分配job
  • 作业中的一组任务(有可能是并行任务)

这些分区可以被视为作业队列, 其中每一个都有各种约束, 如作业大小限制、工作时间限制、允许使用它的用户等。 按照优先级排序的作业,从队列中分配节点,直至该队列分资源,如节点,处理器,内存等耗尽。 一旦一个job分配了一组节点后, 用户就能够按照任何分配配置,以作业步骤形式启动并行工作。 例如, 可以启动一个作业步骤, 利用分配给作业的所有节点, 或者多个作业步骤可以独立地使用分配的一部分。

二、使用

2.1 查看节点与分区

2.1.1 管理分区与节点的状态 – sinfo

sinfo报告由 Slurm 管理的分区和节点的状态。它具有多种筛选、排序和格式设置选项。

[sam@hr-node34 test]$ sinfo
PARTITION AVAIL  TIMELIMIT  NODES  STATE NODELIST
compute*     up   infinite      1  down* hr-node37
compute*     up   infinite      2   idle hr-node[34,36]

2.1.2 查看配置

    scontrol show config

2.1.3 查看分区

[sam@hr-node34 test]$ scontrol show partition
PartitionName=compute
   AllowGroups=ALL AllowAccounts=ALL AllowQos=ALL
   AllocNodes=ALL Default=YES QoS=N/A
   DefaultTime=NONE DisableRootJobs=NO ExclusiveUser=NO GraceTime=0 Hidden=NO
   MaxNodes=UNLIMITED MaxTime=UNLIMITED MinNodes=1 LLN=NO MaxCPUsPerNode=UNLIMITED
   Nodes=hr-node34,hr-node[36-37]
   PriorityJobFactor=1 PriorityTier=1 RootOnly=NO ReqResv=NO OverSubscribe=YES:4 PreemptMode=OFF
   State=UP TotalCPUs=98 TotalNodes=3 SelectTypeParameters=NONE
   DefMemPerNode=UNLIMITED MaxMemPerNode=UNLIMITED

2.1.4 查看节点

通过 /etc/slurm/slurm.conf 查看主节点

    ControlMachine=***

scontrol show node

NodeName=hr-node34 Arch=x86_64 CoresPerSocket=1
   CPUAlloc=0 CPUErr=0 CPUTot=42 CPULoad=1.07
   AvailableFeatures=(null)
   ActiveFeatures=(null)
   Gres=(null)
   NodeAddr=hr-node34 NodeHostName=hr-node34 Version=16.05
   OS=Linux RealMemory=128613 AllocMem=0 FreeMem=3898 Sockets=42 Boards=1
   State=IDLE ThreadsPerCore=1 TmpDisk=2686479 Weight=1 Owner=N/A MCS_label=N/A
   BootTime=2018-07-18T22:58:44 SlurmdStartTime=2018-07-19T00:38:04
   CapWatts=n/a
   CurrentWatts=0 LowestJoules=0 ConsumedJoules=0
   ExtSensorsJoules=n/s ExtSensorsWatts=0 ExtSensorsTemp=n/s

2.1.5 查看作业

    scontrol show jobs

2.1.6 管理的作业、分区和节点的状态信息–smap

smap报告由 Slurm 管理的作业、分区和节点的状态信息, 但以图形方式显示信息以反映网络拓扑。

2.2 作业管理

2.2.1 单个提交作业

# srun hostname
mycentos6x

# srun -N 3 -l hostname
: mycentos6x
: mycentos6x1
: mycentos6x2

# srun sleep 60 &

2.2.2 提交脚本

vim run.slurm

#!/bin/bash
#SBATCH -J test
#SBATCH -p compute
#SBATCH --cpus-per-task=4
#SBATCH --output=/mnt/nfs/sam/test
#SBATCH --error=/mnt/nfs/sam/test

time
echo 'wwww'

运行结果:

[sam@hr-node34 test]$ srun run.slurm
wwww

real    0m0.000s
user    0m0.000s
sys     0m0.000s

2.2.3 追踪任务

SLURM 提供了丰富的追踪任务的命令,例如 scontrol,sacct 等。这些 命令有助于查看正在运行或已完成的任务状态。当用户认为任务异常时,可使用这些 工具来追踪任务的信息。

对于正在运行或排队的任务,可以使用

$ scontrol show job JOBID

其中 JOBID 是正在运行的作业 ID,如果忘记 ID 可以使用,可以查看用户下的运行任务

    squeue -u USERNAME 

查看目前处于运行中的作业。

[liuhy@admin playground]$ squeue
                         JOBID PARTITION     NAME     USER ST       TIME  NODES NODELIST(REASON)
                             140       cpu     test    liuhy  R       0:01      1 comput1
[liuhy@admin playground]$ scontrol show job 140
JobId=140 JobName=test
     UserId=liuhy(502) GroupId=users(100) MCS_label=N/A
     Priority=283 Nice=0 Account=root QOS=normal
     ... (more information) ...

则会输出从 MM 月 DD 日起的所有历史作业。

    $ sacct -S MMDD

默认情况会输出作业 ID,作业名,分区,账户,分配的 CPU,任务结束状态,返回码。 当然我们还可以使用 –format 参数来指定到底要输出那些指标。

[liuhy@admin playground]$ sacct --format=jobid,user,alloccpu,allocgres,state%15,exitcode
             JobID      User  AllocCPUS    AllocGRES           State ExitCode
------------ --------- ---------- ------------ --------------- --------
104              liuhy          1        gpu:1       COMPLETED      0:0
104.extern                      1        gpu:1       COMPLETED      0:0
105              liuhy          1                    COMPLETED      0:0
105.extern                      1                    COMPLETED      0:0
108              liuhy         48                    COMPLETED      0:0
108.extern                     48                    COMPLETED      0:0
126              liuhy          4                    COMPLETED      0:0
126.extern                      4                    COMPLETED      0:0
140              liuhy         12                    COMPLETED      0:0
140.batch                      12                    COMPLETED      0:0
140.extern                     12                    COMPLETED      0:0
141              liuhy         12               CANCELLED by 0      0:0
141.batch                      12                    CANCELLED     0:15
141.extern                     12                    COMPLETED      0:0
142              liuhy          1                       FAILED      2:0
142.extern                      1                    COMPLETED      0:0
142.0                           1                       FAILED      2:0     

在这里我们详细显示了作业 ID,用户,申请的 CPU,申请的 GPU,任务结束状态, 返回码,其中我们比较感兴趣的是任务结束状态。在这里我们看到,JOBID 为 141 的 作业的状态是 CANCELLED by 0,这里 0 表示系统的 root 用户。这条信息表示:我们 的任务被集群的超级管理员强制取消了!这就需要询问管理员具体的原因了。另外, JOBID 为 142 作业的状态是 FAILED,它的含义是我们的作业脚本中有命令异常退出, 这时候就需要检查我们的 SLURM 脚本的命令部分或者是查看运行环境了。

2.2.4 更新任务

有时我们很早就提交了任务,但是在任务开始前却发现作业的属性写错了(例如提交错 了分区,忘记申请 GPU 个数),取消了重新排队似乎很不划算。如果作业恰好没在运行 我们是可以通过 scontrol 命令来修改作业的属性。

使用以下命令可以修改 JOBID 任务的部分属性

    scontrol update jobid=JOBID ...

由于可修改的属性非常多,我们可以借助 SLURM 自动补全功能来查看可修改的内容。 这只需要我们在输入完 JOBID 后空一格并敲两下 键。

[liuhy@admin ~]$ scontrol update jobid=938 <TAB><TAB>
account=<account>                      mintmpdisknode=<megabytes>             reqnodelist=<nodes>
conn-type=<type>                       name>                                  reqsockets=<count>
contiguous=<yes|no>                    name=<name>                            reqthreads=<count>
dependency=<dependency_list>           nice[=delta]                           requeue=<0|1>
eligibletime=yyyy-mm-dd                nodelist=<nodes>                       reservationname=<name>
excnodelist=<nodes>                    numcpus=<min_count[-max_count]         rotate=<yes|no>
features=<features>                    numnodes=<min_count[-max_count]>       shared=<yes|no>
geometry=<geo>                         numtasks=<count>                       starttime=yyyy-mm-dd
gres=<list>                            or                                     switches=<count>[@<max-time-to-wait>]
licenses=<name>                        partition=<name>                       timelimit=[d-]h:m:s
mincpusnode=<count>                    priority=<number>                      userid=<UID
minmemorycpu=<megabytes>               qos=<name>                             wckey=<key>
minmemorynode=<megabytes>              reqcores=<count>

例如我要更改当前的分区到 gpu,并且申请 1 块卡,可以输入

scontrol update jobid=938 partition=gpu gres=gpu:1

注意变更的时候仍然不能超过系统规定的上限。变更成功后,作业的优先级可能需要重新 来计算。

当任务已经开始运行时,一般不可以再变更申请资源,分区等参数。特别地,如果发现 自己低估了任务运行时间,用户不能使用 scontrol 命令延长任务最大时间。但是可以 根据需求减少任务的最大时间。若确实有延长任务时间的急切需求请联系管理员。

2.2.5 使用作业数组(Job Array)

很多时候我们需要运行一组作业,这些作业所需的资源和内容非常相似,只是一些参数 不相同。这个时候借助 Job Array 就可以很方便地批量提交这些作业。Job Array 中的 每一个作业在调度时视为独立的作业,仍然受到队列以及服务器的资源限制。

在 SLURM 脚本中使用 #SBATCH -a range 即可指定 Job Array 的数字范围,其中的 range 参数需要是连续或不连续的整数。下面几种指定方式都是合法的。

  • SBATCH -a 0-9 作业编号范围是 0 到 9,均含边界。
  • SBATCH -a 0,2,4 作业编号是 0,2,4。
  • SBATCH -a 0-5:2 同上,作业编号为 0,2,4,这个写法的意义相当于 MATLAB 中 的 0:2:5,即间隔变成 2。
  • SBATCH -a 0-9,20,40 混合指定也是可以的。

在脚本运行中,SLURM 使用环境变量来表示作业数组,具体为

  • SLURM_ARRAY_JOB_ID 作业数组中第一个作业的 ID。
  • SLURM_ARRAY_TASK_ID 该作业在数组中的索引。
  • SLURM_ARRAY_TASK_COUNT 作业数组中作业总数。
  • SLURM_ARRAY_TASK_MAX 作业数组中最后一个作业的索引。
  • SLURM_ARRAY_TASK_MIN 作业数组中第一个作业的做引。

可用以上变量来区分不同组内的任务,以便于处理不同的输入参数。

对于每个数组内的作业,它的默认输出文件的命名方式为 slurm-JOBID_TASKID.out。

下面是一个很小的 SLURM 脚本例子,它使用 Job Array 来返回一些预设数组中的不同元素。 在实际应用中,这些不同的字符串或许就是程序所需输入的文件名。当然你也可以使用一 个脚本来包装你的程序,然后在这个脚本中获取这个环境变量。

array.slurm

#!/bin/bash
#SBATCH -J array
#SBATCH -p cpu
#SBATCH -N 1
#SBATCH --cpus-per-task=1
#SBATCH -t 5:00
#SBATCH -a 0-2

input=(foo bar baz)
echo "This is job #${SLURM_ARRAY_JOB_ID}, with parameter ${input[$SLURM_ARRAY_TASK_ID]}"
echo "There are ${SLURM_ARRAY_TASK_COUNT} task(s) in the array."
echo "  Max index is ${SLURM_ARRAY_TASK_MAX}"
echo "  Min index is ${SLURM_ARRAY_TASK_MIN}"
sleep 5

提交以上脚本并使用 squeue 命令查看可以看到下面的结果:

[liuhy@admin playground]$ sbatch array.slurm
Submitted batch job 50
[liuhy@admin playground]$ squeue
             JOBID PARTITION     NAME     USER ST       TIME  NODES NODELIST(REASON)
              50_0       cpu    array    liuhy  R       0:01      1 comput1
              50_1       cpu    array    liuhy  R       0:01      1 comput1
              50_2       cpu    array    liuhy  R       0:01      1 comput1

2.2.6 取消作业 –scancel

scancel用于取消挂起或正在运行的作业或作业步骤。它还可用于向与正在运行的作业或作业步骤关联的所有进程发送任意信号。

scancel job_id

参考资料

个人公众号,比较懒,很少更新,可以在上面提问题,如果回复不及时,可发邮件给我: tiehan@sina.cn

Sam avatar
About Sam
专注生物信息 专注转化医学