title: 如何利用SLURM在集群上运行程序 nav_order: 1 parent: 使用须知 —

如何利用SLURM在集群上运行程序

服务器上已经有很多用户在运行程序了, 你不可以和其他人一起抢占资源 (最终导致炸服). 另外, 我们的登陆节点性能也不如计算节点好. 我们的服务器集群使用 SLURM, 一套自动化资源分配的作业调度工具, 帮助你提交作业到计算节点上运行. 当你的程序需要很长的运行时间或者很大的内存占用时, 请使用 slurm 提交程序.

user-topology

申请资源与提交作业

将你想要运行的一条或多条指令称为作业 (job). SLURM 提供了运行作业的三种方式:

srun

官方文档: https://slurm.schedmd.com/srun.html

直接在你要运行的程序前加一个 srun, slurm 就会自动帮你把这个程序放到可用的计算节点上运行. 比如, 原本需要运行 python3 helloworld.py, 现在就可以输入

srun python3 helloworld.py

salloc

官方文档: https://slurm.schedmd.com/salloc.html

salloc相当于向slurm申请计算资源, 然后直接登陆到计算节点上操作.

[yjzhang@loginNode ~]$ salloc
salloc: Granted job allocation 2984
salloc: Waiting for resource configuration
salloc: Nodes bigMem1 are ready for job
[yjzhang@loginNode ~]$ ssh bigMem1
[yjzhang@bigMem1 ~]$ exit
logout
Connection to 192.168.2.11 closed.
[yjzhang@loginNode ~]$ exit
exit
salloc: Relinquishing job allocation 2984
salloc: Job allocation 2984 has been revoked.

首先, 用 salloc 申请资源, 然后通过 ssh 登录到分配的计算节点上. 输入一次 exit 回退到登陆节点, 再输入一次 exit 将任务结束 (请务必记得结束任务, 避免占用不使用的资源).

注意: salloc 会创建一个新的bash环境, 因此你在登陆节点上加载的模块和设置的环境变量都需要重新加载和设置.

sbatch

官方文档: https://slurm.schedmd.com/sbatch.html

可以把所有需要运行的命令写进一个脚本里, 然后通过 sbatch 提交. 脚本就是平时的 shell 脚本, 以 #!/bin/bash 开头. 例如:

#!/bin/bash
module load MATLAB
matlab -batch "testMatlab"

接下来, 用 sbatch <shell script> 提交作业, 其中 <shell script> 是你刚写的脚本名. 屏幕上会打印 Submitted batch job ###, 其中 ### 是你的作业 id. 当作业结束后, 输出结果会打印到当前目录下的 slurm-###.out.

注意: 和 salloc 不同的是, sbatch 会继承你在登陆节点上加载的模块和设置的环境变量.

申请资源选项

在上述案例中, 无论是 srun, salloc 还是 sbatch 都默认你申请一个计算节点, 启动一个进程, 不使用GPU, 并有默认的运行时长上限. 如果你想要申请更多资源 (比如你需要使用GPU, 就必须加上GPU选项!), 或者指定一些运行设定, 都可以添加选项.

比如, 加 -t 30 表示申请运行30分钟的任务, 就直接把选项加在命令后面:

srun -t 30 python3 helloworld.py
salloc -t 30
sbatch -t 30 test.sh

请注意,选项必须紧跟命令。

  • ❌ 错误示例: sbatch test.sh -t 30
  • ✅ 正确示例: sbatch -t 30 test.sh

对于 sbatch, 还可以把选项放在脚本的开头, 以 #SBATCH 开头, 而且必须接在 #!/bin/bash 的后面, 放在所有的命令前面, 否则就会被当成普通的注释. 比如:

#!/bin/bash
#SBATCH -t 30
pwd; hostname; date
echo "Running python on the server"
python3 helloworld.py

下面介绍一些其它常用选项. 长选项和短选项都是可用的, 短选项备注在括号中 (若存在).

选项 默认值 描述
--nodes=<number> (-N <number>) 1 分配的节点数, 由于目前只有两个计算节点, 因此最大值为2.
--ntasks=<number> (-n <number>) 1 启动的进程数量, 当你运行MPI程序时需要修改这个选项.
--cpus-per-task=<number> (-c <number>) 1 每个进程使用的线程数(逻辑核数), 当你运行OpenMP程序时需要修改这个选项.
--nodelist=<node_name_list> (-w <node_name_list>)   指定在哪台机器上运行, 可能的值为 bigMem{0-3}.
--gres=gpu:[gpu_type:]:<number> 指定要用的 gpu 数量或类型, 如 --gres=gpu:1 不指定类型, 或 --gres=gpu:tesla_t4:1, --gres=gpu:nvidia_a30:1. 其中 tesla_t4表示 bigMem0 上的 GPU, nvidia_a30 表示 bigMem1 上的 GPU, bigMem2 上的GPU为AMD系GPU, 暂无访问控制. 目前只支持这三种类型的 GPU. GPU的性能详见我们的Benchmark页面
--job-name=<jobname> (-J <jobname>) 命令名 作业的名称, 有助于帮助你记录你正在运行什么作业.
--output=<path>/<file pattern> (-o <path>/<file pattern>) slurm-%j.out (%j = JobID) 指定标准输出文件的路径以及名字.
--error=<path>/<file pattern> (-e <path>/<file pattern>) slurm-%j.out (%j = JobID) 指定错误输出文件的路径以及名字.
--time=<walltime> (-t <walltime>) 1 天 运行任务的时间限制, 格式如下 [hours:]minutes[:seconds] 如 20, 01:20, 01:20:30 days-hours[:minutes][:seconds] 如 2-0, 1-5:20, 1-5:20:30

小练习

以下哪个说法是正确的?

其他常用命令

sinfo

官方文档: https://slurm.schedmd.com/sinfo.html

sinfo命令报告分区和节点的状态.

$ sinfo
 PARTITION AVAIL  TIMELIMIT  NODES  STATE NODELIST                          GRES
partition*    up 7-00:00:00      1   idle bigMem0          gpu:tesla_t4:4(S:0-1)
partition*    up 7-00:00:00      1   idle bigMem1        gpu:nvidia_a30:4(S:0-1)
partition*    up 7-00:00:00      1   idle bigMem2                         (null)

上述输出表示有三个计算节点, bigMem0, bigMem1 和 bigMem2 状态是 idle 即完全空闲的 (如果显示 mix, 表示有一部分核被用户使用了; 如果显示 alloc, 表示该计算节点的所有核都被占用了, 此时其他用户无法再申请那台机器上的资源), 作业的时间限制最长为7天, 以及三台机器上分别拥有的 GPU 卡数及型号.

squeue & scancel

官方文档: https://slurm.schedmd.com/squeue.html, https://slurm.schedmd.com/scancel.html

在等待你的程序执行的同时, 你可以通过 squeue 知道程序的状态. 例如, 在 loginNode 上列出所有正在队列中的作业:

squeue

你会看到

   JOBID NODELIST         NAME     USER ST       TIME CPUS             END_TIME REQ_NODE
   15341  bigMem2    seurat.sh    gszou  R    6:55:02   32  2024-02-06T14:33:19  bigMem2
   15351  bigMem3 correctness.  yjzhang  R    6:55:02  256  2024-02-06T14:33:19
   15366  bigMem1 starmapMPFC_    gszou  R    6:40:35    2  2024-02-06T14:47:46  bigMem1
   15367  bigMem1 starmapMPFC_    gszou  R    6:40:35    2  2024-02-06T14:47:46  bigMem1
   15368  bigMem1 starmapMPFC_    gszou  R    6:40:35    2  2024-02-06T14:47:46  bigMem1
   15369  bigMem0 starmapMPFC_    gszou  R    6:55:02    2  2024-02-06T14:33:19  bigMem0
   15370  bigMem0 starmapMPFC_    gszou  R    6:55:02    2  2024-02-06T14:33:19  bigMem0
   15371  bigMem0 starmapMPFC_    gszou  R    6:55:02    2  2024-02-06T14:33:19  bigMem0
   15378  bigMem0  interactive   yjshao  R    6:55:42    2  2024-01-31T14:32:39
   15379  bigMem1 HTucker3D_HL    jyliu  R    6:40:08    2  2024-02-06T14:48:13  bigMem1
   15383  bigMem0  explore_cpu   yjshao  R    3:14:02   10  2024-02-06T18:14:19
   15384  bigMem0  explore_cpu   yjshao  R    2:54:18   10  2024-02-06T18:34:03

如果你不想再运行作业, 请使用以下命令取消它:

scancel <jobid>

scontrol

官方文档: https://slurm.schedmd.com/scontrol.html

提交作业后你会得到一个作业号, 以下用 <jobid> 表示. 如果忘了你的作业号, 且你的作业还没有运行结束, 可以通过 squeue 命令查看你的作业编号.

用以下命令查看你提交的作业状态:

scontrol show job <jobid>

用以下命令查看节点的状态:

scontrol show node <nodename>

例如

[yjzhang@loginNode ~]$ scontrol show node bigMem0
NodeName=bigMem0 Arch=x86_64 CoresPerSocket=16
   CPUAlloc=28 CPUEfctv=64 CPUTot=64 CPULoad=3.78
   AvailableFeatures=(null)
   ActiveFeatures=(null)
   Gres=gpu:tesla_t4:4(S:0-1)
   NodeAddr=bigMem0 NodeHostName=bigMem0 Version=22.05.2
   OS=Linux 3.10.0-1160.36.2.el7.x86_64 #1 SMP Wed Jul 21 11:57:15 UTC 2021
   RealMemory=1030499 AllocMem=0 FreeMem=717245 Sockets=2 Boards=1
   State=MIXED ThreadsPerCore=2 TmpDisk=0 Weight=1 Owner=N/A MCS_label=N/A
   Partitions=partition
   BootTime=2023-09-11T13:27:35 SlurmdStartTime=2023-11-30T07:26:18
   LastBusyTime=2024-01-30T14:32:36
   CfgTRES=cpu=64,mem=1030499M,billing=64
   AllocTRES=cpu=28
   CapWatts=n/a
   CurrentWatts=0 AveWatts=0
   ExtSensorsJoules=n/s ExtSensorsWatts=0 ExtSensorsTemp=n/s

用以下命令查看系统中的预约信息: ~~~ bash scontrol show reservation ~~~

预约节点资源

(since Feb 1, 2024)

你可能已经注意到了, 服务器上有很多用户在使用资源, 有时你提交作业后, squeue 会显示你的作业状态是 PD (Pending), 表示作业正在排队. 作业排队的原因有很多, 你可以通过 scontrol show job <jobid> 的方式查看具体原因, 在输出内容中, JobState=PENDING 后面会跟着一个 Reason, 显示作业未被执行的原因. 常见的作业未开始执行的原因是 Resources, 即你所申请的资源不可用. 比如, 你申请了 bigMem1 上32核的资源, 但当前已有一个用户使用了 bigMem1 上48核, 这时你的作业就会进入队列排队. 如果对排队的原因有所疑问, 请直接联系服务器管理员.

当你在 loginNode 上使用 squeue 命令时, 你可以看到倒数第二列 END_TIME, 对于正在运行的作业, 这个时间表示作业最晚可能结束的时间, 作业可能比这个时间更早结束, 但绝不会晚于这个时间点 (除非计算节点崩溃, 任务重新排队). 对于正在排队的作业, END_TIME 表示作业预计结束的时间, 并不保证一定会在这个时间点前结束, 且会根据队列的状态实时更新相应的估计. 所以, 如果你希望能在某个确切的时间点前完成任务, 请使用预约制度.

另一种常见的情况是出于测试程序和算法性能的需求, 你想要独占节点资源. 通常, 你可以在 srun/salloc/sbatch 的时候加上选项 --exclusive, 这保证了我们的作业独占这个节点. 下面是关于 --exclusive 的说明 (使用方式请参考申请资源选项)

slurm_exclusive

如果当前有完全空闲 (IDLE) 的计算节点, 则你的作业可以立刻运行. 否则, 你的任务将在队列中排队. 在排队的过程中, 如果有其他用户希望不独占节点地运行任务, 出于计算资源最大化利用的考量, 他们可以插队运行他们的任务. 考虑最坏的情况下, 我们对你的任务最终开始运行的时间没有任何保障. 因此, 如果你对作业运行的时间有所需求, 我们同样建议使用预约制度.

预约节点资源就像在饭店里预定座位一样, 你可以预订从某个时间点开始到某个时间点结束, 只有你指定的一部分用户可以使用你指定的一部分节点. 一旦节点被预约, 则其他用户无法提交可能结束时间晚于预约开始时间的作业. 如果你需要预约节点, 请发邮件至管理员邮箱. 邮件内容必须包括:

  1. 预约开始时间 (精确到某一个小时,如北京时间2月1日上午9点) 和预约结束时间 (精确到某一个小时,如北京时间2月4日上午9点). 除非有特殊需求,否则预约时间不得超过七天.
  2. 预约的节点名称, bigMem0, bigMem1, bigMem2 或 bigMem3. 除非有特殊需求,否则预约节点数不得超过一个.
  3. 预约的核数, 如无特殊声明, 默认为预约节点上所有核. (bigMem0 - 64核, bigMem1 - 64核, bigMem2 - 128核, bigMem3 - 512核)
  4. 需要在这段时间内使用节点的用户名称, 用逗号分隔. 如: xli, yjzhang, jyliu.
  5. 使用节点的具体用途.

预约条件: 预约开始时间必须晚于当前节点正在运行的任务的最终结束时间, 请提前用 squeue 查看节点状态. 此外, 每一个被包含在上述用户列表中的用户每个月有1024核时的额度, 且预约次数不得超过3次. 若超出额度, 则需要提供导师知情且同意的证明.

例:

发送邮件后, 管理员会及时和你联系, 告知预约是否成功. 预约成功后, 请在预约时间内用 slurm 提交任务. 如果管理员在24小时内连续两次看到被预约的节点并没有在运行任何任务, 管理员有权取消你的预约. 若多次违约, 管理员有权取消你的预约资格.