一、Slurm常规运行操作
在HPC上运行任务的主要方法是通过sbatch命令提交一个脚本。例如:
sabtch MyJobScript.sh
在MyJobScript.sh中的命令会在第一个被找到的、可用的、满足资源要求的compute node上进行运算,sbatch会在提交任务后立刻返回一个信息。提交的命令不会作为前台进程运行,并且也不会在断开HPC连接之后停止运行。
编写SBATCH脚本通常来说,一个sbatch脚本分为3个部分:#!/bin/bash 这一行使得脚本可以作为一个bash script运行;以#SBATCH开头的行理论上是bash命令,但是它们实际上设置了SLURM调度程序的各种参数;要运行的命令。注意,我们应当把所有的#SBATCH开头的行放在一起,同时放在脚本的顶部。必须在所有的#SBATCH行结束之后才能写bash code和变量设置。
一个典型的任务提交脚本如下所示:
'''
#!/bin/bash
#SBATCH -n 1 # 指定核心数量
#SBATCH -N 1 # 指定node的数量
#SBATCH -t 0-5:00 # 运行总时间,天数-小时数-分钟, D-HH:MM
#SBATCH -p debug # 提交到哪一个分区
#SBATCH --mem=2000 # 所有核心可以使用的内存池大小,MB为单位
#SBATCH -o myjob.o # 把输出结果STDOUT保存在哪一个文件
#SBATCH -e myjob.e # 把报错结果STDERR保存在哪一个文件
#SBATCH --mail-type=ALL # 发送哪一种email通知:BEGIN,END,FAIL,ALL
#SBATCH [email protected] # 把通知发送到哪一个邮箱
#SBATCH --constraint=2630v3 # the Features of the nodes, using command " showcluster " could find them.
#SBATCH --gres=gpu:n # 需要使用多少GPU,n是需要的数量
runYourCommandHere
SLURM系统会将许多环境变量(包括PATH和当前工作目录)从当前会话复制到运行脚本的计算主机。因此,您在指定文件位置的时候,可以只指定改文件相对于当前位置的位置(例如./project/myfiles/myfile.txt)。
[补充:要注意,对于Python多处理作业,您需要指定-c 16,而不是{},因为后者可能会在不同的节点(服务器)上分配作业,multiprocessing模块无法处理这些任务,而前者将确保所有保留的核心都在同一节点上。]
对上述脚本文件的逐行讲解:
#SBATCH -n 1 or --ntasks=1
这一行指定了你需要的核心数量。只有在你使用的程序本身能够使用多核运行的时候,你才应该请求多个核心。如果这个参数省略不写,那么SLURM会假设你只请求一个核心。
一些科学计算工具是支持多进程运行的。但是也有一些是不支持的,例如常规的R脚本都是不支持多线程的。
#SBATCH -N 1 or --nodes=1
这一行设置了你需要的node数量。如果说你使用了MPI,并且在一个node上需要多个核心,你应当计算清楚具体需要多少node和核心。
#SBATCH -t 0-5:00 or --time=05:00:00
这一行说明了任务的最大运行时间(单位是分钟)。如果你的任务事实上需要的运行时间大于你设定的值,那么你的任务会在到达最大运行时间时被终止。如果这个参数省略不写,那么你的任务会被安排30分钟的最大运行时间。
#SBATCH -p serial or --partition=serial
这一行指定了你的脚本会在哪个SLURM partition运行。Partition是SLURM使用的关于队列的术语,是在使用SLURM中的一系列资源和参数的集合。
#SBATCH --mem=2000
在使用HPC cluster的时候,应当指定需要的内存数量(以MB为单位),这样可以让系统上的各个工作以最大的效率运行。
这是在发起资源申请的时候最重要的参数。如果你申请的内存量小于你的程序需要的量,那么程序会在运行途中crash。如果你申请的内存量远大于你的程序需要的量,那么本可以用于其他任务的资源就被浪费了。此外,每个人都有一个“fairshare”值用于计划工作优先级,如果你总是超额很多请求资源,你的工作优先级会下降。
我们可以通过两个参数指定需要的内存大小,第一个是--mem,第二个是--mem-per-cpu。第一种方式--mem可以指定整个一个或者多个核心可用的整个内存池的大小,是被推荐使用的方式。当我们需要做跨多节点的计算任务时,我们必须使用第二种方式--mem-per-cpu,因为这种方式可以指定好分配给每一个核心具体内存大小。
--mem和--mem-per-cpu在运行多核任务时有很大区别(对于单核作业,两者是等效的)。 --mem设置所有内核的总内存,而--mem-per-cpu设置了内核的内存。 如果使用--mem请求两个内核(-n 2)和4 Gb内存,那么每个内核将有2 GB RAM。 如果使用--mem-per-cpu指定4 Gb,则每个内核有4 GB RAM,总计8 GB。
如果我们省略这个参数不写,那么我们会得到最小的分配大小,通常是2000MB。如果我们的程序在运行中超过了我们申请的内存大小,那么任务会被结束。
#SBATCH -o myjob.o or --output=myjob.o
这行命令指定了标准输出standard out会被添加到哪个文件里面。如果我们指定的是一个相对路径,那么文件会被保存在当前的工作目录下。如果这个参数被省略了,那么所有的输出都会被储存在当前工作目录的一个名为slurm-JOBID.out的文件里面。
#SBATCH -e myjob.e or --error=myjob.e
这行命令指定了标准错误信息standard error会被添加到哪个文件里面,此外SLURM提交和处理时的错误也会被保存在这个文件。如果这个参数被省略了,那么所有的输出都会被储存在当前工作目录的一个名为slurm-JOBID.out的文件里面。
#SBATCH --mail-type=ALL
因为我们的任务是在后台被处理的,因此当任务完成以后(--mail-type=END)发送一封邮件给我们有利于我们知道任务的处理进度。,我们也可以选择在其他处理阶段发送邮件,例如开始START、失败FAIL、和所有阶段(ALL)。
#SBATCH [email protected]
指定了将--mail-type信息发送到哪一个邮箱地址。
#SBATCH --constraint=2630v3
这一行指定了将任务提交到feature是2630v3的nodes。
#SBATCH --gres=gpu:n
当我们需要使用GPU进行计算的时候,需要加上这一行。n的值就是需要的GPU数量。如果在运行中不需要用到GPU,那么不要写这一行。
监控任务进度
我们通常使用squeue和sacct来监控在SLURM中的作业活动。squeue是最重要、最准确的监控工具,因为它可以直接查询SLURM控制器。sacct也可以报告之前完成的任务,但是因为它是通过查询SLURM database获取信息,因此有时候sacct查到的信息和squeue查到的信息会有一点区别。
运行在不附带arguments的情况下运行squeue会显示所有当前正在运行的任务。当使用 squeue -u yourUserName的时候,会只显示你提交的任务。
squeue -u yourUserName
或者是查询一个特定任务:
squeue -j JobID
如果在squeue最后加上了-l选项(意思是long output),那么系统还会返回任务的运行状态。
我们可以通过saact查询特定任务的细节:
sacct -j JobID
但是,由于sacct可以访问到很多SLURM使用的resource accounting fields,它可以比squeue提供更加详细信息。例如,如果要查看用户Michael今日使用的内存资源:
sacct -u michael
使用-j参数查询到的工作状态有等待PENDING、运行中RUNNING、已完成COMPLETED、已取消CANCELLED、失败FAILED:
- PENDING:任务正在等待所需要的资源。如果一个任务需要很大的资源量,那么它也很可能需要PENDING很久。
- RUNNING:任务正在运行中。
- COMPLETED:任务运行完了,并且命令成功returned,也就是退出码exit code是0。
- CANCELLED:任务被用户或者管理员使用scancel命令取消了。
- FAILED:任务完成了,同时退出码不是0。
取消任务
取消任务的方法是输入scancel加上任务的ID:
scancel JobID
我们可以通过squeue -u命令查询到我们需要的任务的ID。
交互式任务
尽管使用批量提交的方式,通常是充分运用HPC的计算资源的方法,但是前台的交互式任务也是可以运行的。通常我们建议在如下情况使用前台的交互式任务:
- 在命令行上迭代地进行数据探索;
- RAM密集型图像应用,例如MATLAB或者SAS;
- 交互式的控制台工具,例如R和IPython;
- 重要的软件开发和编译工具。
在运行交互式任务的时候要注意,我们要指定的partition是interactpartition。
此外在交互式任务中,我们需要用srun,而不是sbatch来初始化。例如,我们要在交互式队列中启动一个命令行shell(/bin/bash),申请500MB内存、6小时运行时间、1个核心、1个node,那么可以输入下面的命令:
srun -p serial --pty --mem 500 -t 0-06:00 /bin/bash
当交互式的session启动以后,你会发现你不在login node里面了,而是位于专门用于此队列的计算节点之一。
--pty命令使得这个session可以像标准的终端一样运行。
在必要的时候,你也可以直接运行一个程序。不过我们不鼓励这样做,因为这会导致在设置环境变量的时候出现问题。在导入一个MATLAB的模块之后,你可以用下面的命令启动这个程序:
srun -p serial --pty --mem=4000 -t 0-06:00 matlab
或者是:
salloc –p serial --mem=4000 --time=02:00:00
srun yourCommand1
srun yourCommand2
srun yourCommand3
…
exit
在HPC上的存储
有两个文件夹可以用来储存,一个是HOME文件夹,位于/gpfsnyu/home,这个文件夹每天会被备份两次,并且会把快照保存一个月;另一个是SCRATCH文件夹,位于/gpfsnyu/scratch,这个文件夹不会被备份,可以放一些乱七八糟的数据文件。
/scratch
/scratch文件系统适合处理大块的输入输出,例如顺序读取和写入大文件。但是,单个的输入输出操作成本相对较高,所以频繁执行小的输入输出的程序将给元数据服务(metadata service)带来很重的负担,在极端情况下甚至会造成系统的不稳定。系统管理员通常会探测到这种频繁的输入输出,并且可能会结束这个任务。
/scratch最适合处理低频的、大的读取和写入,因此,建议用户在这个文件夹处理大文件,而不是数量很多的小文件。如果真的要在执行任务的时候频繁地访问临时文件,应当使用compute node的本地磁盘,甚至是compute node上的RAM文件系统来减少/scratch文件系统的输入输出操作。
通常来说文件系统很难处理把大量的文件放在一个目录的情况,这会儿导致处理这个文件夹的时候会非常的慢,同时也会影响其他用户的使用。一个文件夹中的文件数量应当小于1000个,如果有跟多的文件的时候,应当新建立几个文件夹、分开装。
在/scratch目录下,所有的HPC账户拥有5TB的磁盘空间,但是这个目录中的数据是不进行系统备份的,因此由文件丢失、系统崩溃、硬件损坏造成的数据丢失以后是无法恢复的,因此用户要自己留意备份重要的数据。
由于/scratch文件夹中超过60天没有被使用的文件将被移除,因此不建议把源代码、脚本、库、可执行文件等数据放在这个文件夹,这些重要的文件应该放在/home文件夹下面。此外,也不建议把/scratch中的文件夹软链接到/home文件夹里面。
二、基础知识介绍
1.相关基本概念
资源(Resource)
- 作业运行过程中使用的可量化实体都是资源;
- 包括硬件资源(节点、内存、CPU 、GPU等)和软件资源( License );
集群(Cluster)
- 包含计算、存储、网络等各种资源实体且彼此联系的资源集合;
- 在物理上,一般由计算处理、互联通信、I/O 存储、操作系统、编译器、运行环境、开发工具等多个软硬件子系统组成;
- 节点是集群的基本组成单位,从角色上一般可以划分为管理节点、登陆节点、计算节点、存储节点等。
作业(Job)
- 物理构成,一组关联的资源分配请求,以及一组关联的处理过程;
- 交互方式,可以分为交互式作业和非交互式作业;
- 资源使用,可以分为串行作业和并行作业;
分区(Partition)---节点所在分区
- 带名称的作业容器;
- 用户访问控制;
- 资源使用限制;
作业调度系统(Job Schedule System)
- 负责监控和管理集群中资源和作业的软件系统;
- 通常由资源管理器、调度器、任务执行器,以及用户命令和API组成;
调度系统主要作用
单一系统映像
- 解决集群结构松散问题;
- 统一用户接口,使用简化;
系统资源整合 - 管理异构资源和异构系统;
多任务管理 - 统一管理任务,避免冲突;
资源访问控制 - 基于策略的资源访问控制;
换句话说,调度系统是面向集群的操作系统。
1. Slurm
Slurm是一个开源,容错,高度可扩展的集群管理和作业调度系统,适用于大型和小型Linux集群。Slurm不需要对其操作进行内核修改,并且相对独立。作为集群工作负载管理器,Slurm有三个关键功能。首先,它在一段时间内为用户分配对资源(计算节点)的独占和/或非独占访问,以便他们可以执行工作。其次,它提供了一个框架,用于在分配的节点集上启动,执行和监视工作(通常是并行作业)。最后,它通过管理待处理工作的队列来仲裁资源争用。
2.Slurm的运行架构
(1)主控服务slurmctld
故障切换 资源监控 队列管理 作业调度
(2)记账存储服务slurmdbd
记账数据 配置信息 故障切换
(3)数据库MySQL
记账和配置信息存储
(4)计算代理slurmd
启动任务 监控任务 分层通信
(5)认证服务munge
内部通信认证
3.Slurm的主要特点
- 架构设计优秀
扩展性(功能/规模)高性能(提交/调度)灵活性(自定义插件)容错性(服务/节点/作业
- 特色功能突出
资源绑定(CPU、MEM、类GPU加速卡等各类资源)关联调度(如类GPU加速卡关联CPU)
能耗管理(限频、开关机、记账等)拓扑调度(基于拓扑结构调度,限定交换机数等)
基础功能完善
优先级策略(Multi-Factor)
作业调度(FairShare/Backfill/ FCFS, etc)
资源竞争(Exclusive/Preempt/Gang, etc)
多级限制(Cluster/Account/User/Partition, etc)
资源预留(CPU/MEM/类GPU加速卡/License等)兼容性/交互性良好
MPI兼容(IntelMPI/MVAPICH/OpenMPI,etc)
LSF兼容(bsub/bjobs/bqueue/bhosts, etc)
PBS兼容(qsub/qstat/pbsnodes/pestat, etc)
分析工具(融合Influxdb/ES/HDF5等,方便分析)
4.三种模式
- 批处理作业(采用sbatch命令提交,最常用方式):
对于批处理作业(提交后立即返回该命令行终端,用户可进行其它操作)使用sbatch命令提交作业脚本,作业被调度运行后,在所分配的首个节点上执行作业脚本。在作业脚本中也可使用srun命令加载作业任务。提交时采用的命令行终端终止,也不影响作业运行。
- 交互式作业提交(采用srun命令提交):
资源分配与任务加载两步均通过srun命令进行:当在登录shell中执行srun命令时,srun首先向系统提交作业请求并等待资源分配,然后在所分配的节点上加载作业任务。采用该模式,用户在该终端需等待任务结束才能继续其它操作,在作业结束前,如果提交时的命令行终端断开,则任务终止。一般用于短时间小作业测试。
- 实时分配模式作业(采用salloc命令提交):
分配作业模式类似于交互式作业模式和批处理作业模式的融合。用户需指定所需要的资源条件,向资源管理器提出作业的资源分配请求。提交后,作业处于排队,当用户请求资源被满足时,将在用户提交作业的节点上执行用户所指定的命令,指定的命令执行结束后,运行结束,用户申请的资源被释放。在作业结束前,如果提交时的命令行终端断开,则任务终止。典型用途是分配资源并启动一个shell,然后在这个shell中利用srun运行并行作业。
注意:
(1)salloc后面如果没有跟定相应的脚本或可执行文件,则默认选择/bin/sh,用户获得了一个合适环境变量的shell环境。
(2)salloc和sbatch最主要的区别是salloc命令资源请求被满足时,直接在提交作业的节点执行相应任务,而sbatch则当资源请求被满足时,在分配的第一个节点上执行相应任务。
(3)salloc在分配资源后,再执行相应的任务,很适合需要指定运行节点和其它资源限制,并有特定命令的作业。
5.相关命令
(1)查看分区——sinfo
(2)查询排队和运行状态的作业——squeue
(3)删除作业命令——scancel
(4)控制作业命令——scontrol