博士期间我一直用的是生信技能树的服务器【搭配GPU服务再升级—256线程2Tb内存服务器共享一年仍然是仅需800】,这个价格非常适合学生党,可以帮助我们低成本快速练习Linux技能,美中不足的是技能树的服务器没有作业调度系统。由于我过去四年没有这方面的使用背景,我完全不适应新单位的集群系统。实际上,大规模以及长期运行的数据需要提交任务至分配节点,如果在登录节点运行较大资源的话,会导致整个服务器卡顿(还可能会被别的用户吐槽,甚至被管理员处罚...)。在这里,我分享一下关于Slurm学习笔记。
Slurm(Simple Linux Utility for Resource Management)是一个常用的作业调度系统,已被全世界的国家超级计算机中心广泛采用,它可以管理计算集群上的资源,并调度和执行作业(例如脚本或分析任务),帮助用户高效地在多个计算节点上运行任务。
Slurm 的基本概念
作业 (Job): 用户提交给集群去执行的任务,例如运行一个脚本。
节点 (Node): 集群中的一台计算机,负责执行作业。
登录节点 (Login Node): 用户通过 SSH 进入集群后最初登录的节点。它用于准备作业、编写脚本和提交作业,但不是作业执行的地方。 分配节点 (Allocated Node): 当你提交作业并成功分配资源时,作业将在这些节点上运行,它们由 Slurm 根据你的资源需求来选择。 分区 (Partition): 一组节点的集合(也可以叫做“队列”),不同分区可能有不同的资源配置或策略。
调度器 (Scheduler): Slurm 根据资源可用性和作业的优先级,决定作业何时、在哪些节点上执行。
基本工作流程
提交作业: 用户通过
sbatch
命令提交编写好的作业脚本,描述作业的资源需求(如节点数、CPU数、内存等)和执行命令,或者使用srun
运行交互式作业。资源分配:Slurm的调度器根据当前的资源可用情况和作业队列中的优先级,分配资源给新提交的作业。
监控作业: 使用
squeue
查看作业的状态(例如,正在运行或等待中)。作业输出: 作业完成后,输出通常会保存在用户指定的文件中。
Slurm 概览
Slurm | 功能 |
---|---|
sinfo | 集群状态 |
srun | 启动交互式作业 |
squeue | 排队作业状态,当前作业状态监控 |
sbatch | 作业/脚本提交 |
scontrol | 查看和修改作业参数 |
sacct | 显示用户的作业历史,默认情况下,sacct显示过去 24小时 的账号作业信息。 |
scancel | 删除作业 |
sreport | 生成使用报告 |
sinfo
查看集群状态和信息
Slurm | 功能 |
---|---|
sinfo -s | 简要格式输出 |
sinfo -N | 查看节点级信息 |
sinfo -N --states=idle | 查看可用节点信息 |
sinfo --partition=cpu | 查看队列信息 |
sinfo --help | 查看所有选项 |
输出字段:
PARTITION: 分区名称 AVAIL: 节点可用性状态(up/down) TIMELIMIT: 分区的时间限制 NODES: 分区中的节点数量 STATE: 节点状态: drain
(节点故障),alloc
(节点在用),idle
(节点可用),down
(节点下线),mix
(节点被占用,但仍有剩余资源)NODELIST: 节点名称列表
查看总体资源信息:
sinfo
#PARTITION AVAIL TIMELIMIT NODES STATE NODELIST
#cpu up 7-00:00:0 656 idle cas[001-656]
#dgx2 up 7-00:00:0 8 idle vol[01-08]
查看某个特定节点的信息:
sinfo -n <节点名称>
sacct
显示用户作业历史
用途: 查询作业历史记录,显示已完成和正在进行的作业信息,默认情况下,sacct显示过去 24小时 的账号作业信息。
参数:
-j <jobid>
查询特定作业-S <YYYY-MM-DD>
查询指定开始日期的作业-u <username>
查询特定用户的作业输出字段:
JobID: 作业ID
JobName: 作业名称
Partition: 分区名称
Account: 用户账户
State: 作业状态(COMPLETED、FAILED、CANCELLED等)
Elapsed: 作业运行时间
squeue
查看作业信息
Slurm | 功能 |
---|---|
squeue -j <作业的jobid> | 查看作业信息 |
squeue -l | 查看细节信息 |
squeue --nodelist=<节点名称> | 查看特定节点作业信息 |
squeue | 查看USER_LIST的作业 |
squeue --state=R | 查看特定状态的作业 |
squeue --help | 查看所有的选项 |
输出字段:
JOBID: 作业ID PARTITION: 分区名称 NAME: 作业名称 USER: 用户名 ST: 作业状态包括 R
(正在运行),PD
(正在排队),CG
(即将完成),CD
(已完成)TIME: 作业运行时间 NODES: 作业使用的节点数量 NODELIST(REASON): 作业所在节点或排队原因
默认情况下,squeue
只会展示在排队或在运行的作业。
$ squeue
JOBID PARTITION NAME USER ST TIME NODES NODELIST(REASON)
18046 dgx2 ZXLing eenl R 1:35:53 1 vol04
17796 dgx2 python eexdl R 3-00:22:04 1 vol02
显示您自己账户下的作业:
squeue -u <用户名>
JOBID PARTITION NAME USER ST TIME NODES NODELIST(REASON)
17923 dgx2 bash hpcwj R 1-12:59:05 1 vol05
-l
选项可以显示更细节的信息。
squeue -u <用户名> -l
JOBID PARTITION NAME USER STATE TIME TIME_LIMI NODES NODELIST(REASON)
17923 dgx2 bash hpcwj RUNNING 1-13:00:53 30-00:00:00 1 vol05
srun
启动交互式作业
srun --partition=<分区> --nodes=<节点数> --ntasks=<任务数> --t=<时长> --mem=<内存> --c=<调用的CPU数量> --pty bash
运行此命令后,你会获得一个交互式的 shell,能够在该节点上直接执行命令。但是srun的缺点是一旦断线就无法重新连接回去,因此推荐使用Linux终端复用神器tmux/screen+srun配合运行,关于tmux,详见我之前写的推文【Tmux:Linux终端复用神器,包好用】
sbatch
作业提交
准备作业脚本然后通过sbatch
提交是 Slurm 的最常见用法。为了将作业脚本提交给作业系统,Slurm 使用
sbatch my_job_script.sh
Slurm 具有丰富的参数集。以下最常用的。
Slurm | 含义 |
---|---|
-n [count] | 总进程数 |
--ntasks-per-node=[count] | 每台节点上的进程数 |
-p [partition] | 作业队列 |
--job-name=[name] | 作业名 |
--output=[file_name] | 标准输出文件 |
--error=[file_name] | 标准错误文件 |
--time=[dd-hh:mm:ss] | 作业最大运行时长 |
--exclusive | 独占节点 |
--mail-type=[type] | 通知类型,可选 all, fail, end,分别对应全通知、故障通知、结束通知 |
--mail-user=[mail_address] | 通知邮箱 |
--nodelist=[nodes] | 偏好的作业节点 |
--exclude=[nodes] | 避免的作业节点 |
--depend=[state:job_id] | 作业依赖 |
--array=[array_spec] | 序列作业 |
这是一个名为cpu.slurm
的作业脚本,该脚本向cpu队列申请1个节点40核,并在作业完成时通知。在此作业中执行的命令是/bin/hostname
。
#SBATCH --job-name
作业名称#SBATCH --output
标准输出文件:如/share/home/pengchen/work/%x_%A_%a.out#SBATCH --error
ERROR输出文件:如/share/home/pengchen/work/%x_%A_%a.err#SBATCH --partition
工作分区,我们用cpu之类的#SBATCH --nodelist
可以制定在哪个节点运行任务#SBATCH --exclude
可以设置不放在某个节点跑任务#SBATCH --nodes
使用nodes数量#SBATCH --ntasks
tasks数量,可能分配给不同node#SBATCH --ntasks-per-node
每个节点的tasks数量,由于我们只有1 node,所以ntasks和ntasks-per-node是相同的#SBATCH --cpus-per-task
每个task使用的core的数量(默认 1 core per task),同一个task会在同一个node#SBATCH --mem
这个作业要求的内存 (Specified in MB,GB)#SBATCH --mem-per-cpu
每个core要求的内存 (Specified in MB,GB)
#!/bin/bash
#SBATCH --job-name=hostname
#SBATCH --partition=cpu
#SBATCH -N 1
#SBATCH --mail-type=end
#SBATCH --mail-user=YOU@EMAIL.COM
#SBATCH --output=%j.out
#SBATCH --error=%j.err
/bin/hostname
用以下方式提交作业:
sbatch cpu.slurm
squeue
可用于检查作业状态。用户可以在作业执行期间通过SSH登录到计算节点。输出将实时更新到文件[jobid] .out和[jobid] .err。
这里展示一个更复杂的作业要求,其中将启动80个进程,每台主机40个进程。
#!/bin/bash
#SBATCH --job-name=LINPACK
#SBATCH --partition=cpu
#SBATCH -n 80
#SBATCH --ntasks-per-node=40
#SBATCH --mail-type=end
#SBATCH --mail-user=YOU@EMAIL.COM
#SBATCH --output=%j.out
#SBATCH --error=%j.err
以下作业请求4张GPU卡,其中1个CPU进程管理1张GPU卡。
#!/bin/bash
#SBATCH --job-name=GPU_HPL
#SBATCH --partition=dgx2
#SBATCH -n 4
#SBATCH --ntasks-per-node=4
#SBATCH --gres=gpu:4
#SBATCH --mail-type=end
#SBATCH --mail-user=YOU@MAIL.COM
#SBATCH --output=%j.out
#SBATCH --error=%j.err
以下作业启动一个3任务序列(从0到2),每个任务需要1个CPU内核。
#!/bin/bash
#SBATCH --job-name=python_array
#SBATCH --mail-user=YOU@MAIL.COM
#SBATCH --mail-type=ALL
#SBATCH --ntasks=1
#SBATCH --time=00:30:00
#SBATCH --array=0-2
#SBATCH --output=python_array_%A_%a.out
#SBATCH --output=python_array_%A_%a.err
module load miniconda2/4.6.14-gcc-4.8.5
source activate YOUR_ENV_NAME
echo "SLURM_JOBID: " $SLURM_JOBID
echo "SLURM_ARRAY_TASK_ID: " $SLURM_ARRAY_TASK_ID
echo "SLURM_ARRAY_JOB_ID: " $SLURM_ARRAY_JOB_ID
python < vec_${SLURM_ARRAY_TASK_ID}.py
在提交到SLURM的作业脚本中,可以激活Conda环境以确保作业在正确的软件环境中运行。以下是一个示例SLURM作业脚本:
#!/bin/bash
#SBATCH --job-name=myjob # 作业名称
#SBATCH --output=myjob.out # 标准输出和错误日志
#SBATCH --error=myjob.err # 错误日志文件
#SBATCH --ntasks=1 # 运行的任务数
#SBATCH --time=01:00:00 # 运行时间
#SBATCH --partition=compute # 作业提交的分区
# 加载Conda
source ~/miniconda3/etc/profile.d/conda.sh
# 激活环境
conda activate myenv
# 运行命令
python my_script.py
scancel
取消指定作业
用途: 取消一个或多个作业。
示例:
scancel 12345
参数:
-u <username>
取消特定用户的所有作业-p <partition>
取消特定分区中的作业
Slurm环境变量
Slurm | 功能 |
---|---|
$SLURM_JOB_ID | 作业ID |
$SLURM_JOB_NAME | 作业名 |
$SLURM_JOB_PARTITION | 队列的名称 |
$SLURM_NTASKS | 进程总数 |
$SLURM_NTASKS_PER_NODE | 每个节点请求的任务数 |
$SLURM_JOB_NUM_NODES | 节点数 |
$SLURM_JOB_NODELIST | 节点列表 |
$SLURM_LOCALID | 作业中流程的节点本地任务ID |
$SLURM_ARRAY_TASK_ID | 作业序列中的任务ID |
$SLURM_SUBMIT_DIR | 工作目录 |
$SLURM_SUBMIT_HOST | 提交作业的主机名 |
参考资料
上交大的超算平台的手册(https://docs.hpc.sjtu.edu.cn/job/slurm.html)