ixxmu / mp_duty

抓取网络文章到github issues保存
https://archives.duty-machine.now.sh/
122 stars 30 forks source link

学习笔记:slurm作业调度系统 #5770

Closed ixxmu closed 3 weeks ago

ixxmu commented 3 weeks ago

https://mp.weixin.qq.com/s/Y3oVWEhgG_aNlOl_Z4KIhg

ixxmu commented 3 weeks ago

学习笔记:slurm作业调度系统 by 生信菜鸟团

博士期间我一直用的是生信技能树的服务器【搭配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 查看作业的状态(例如,正在运行或等待中)。

  • 作业输出: 作业完成后,输出通常会保存在用户指定的文件中。

image-20241018215519860

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提交作业的主机名

参考资料

ixxmu commented 3 weeks ago

大平台就是就x,这就开始玩集群了,一直没机会搞 😭