第1章 作业调度系统入门:SLURM基础概念、作业提交与监控、作业脚本编写规范

1.1 为什么我们需要作业调度系统?

说实话,我刚入行那会儿,也觉得调度系统挺烦人的。

明明我有代码,有数据,直接跑不就完了?干嘛还要学一套新工具?

后来我接手了一个集群,有32个节点,每个节点64核。好家伙,大家一窝蜂往上提交任务,结果呢?

  • 有人占了全部内存,别人跑不了
  • 有人开了100个进程,把CPU打满了
  • 还有人跑着跑着断连了,作业直接丢了

嗯,这时候我才明白——没有调度系统的集群,就是菜市场。

SLURM就是那个「管理员」。它帮你排队、分配资源、监控状态。说白了,它是高通量计算的基石。

核心认知:SLURM不是用来限制你的,而是用来保护你的。保护你的作业不被别人干扰,也保护别人不被你干扰。

1.2 SLURM的三大核心组件

我习惯把SLURM理解成一个「三驾马车」的结构。你想想看,一个调度系统要干三件事:

  • 知道集群有什么资源 —— 谁在干活?谁闲着?
  • 决定谁先跑 —— 排队、优先级、抢占
  • 执行任务 —— 把作业发到计算节点上

对应到SLURM里,就是三个角色:

组件 角色 我常说的比喻
slurmctld 中央控制器 「大管家」—— 管排队、管分配
slurmd 计算节点守护进程 「分店店长」—— 听大管家指挥,干活
sacctmgr / sacct 账户与记账工具 「财务」—— 谁用了多少资源,记下来

我在项目中遇到过一个问题:slurmctld挂了,所有作业都卡住了。为什么?因为「大管家」不在,没人知道下一步该干啥。所以生产环境一定要做高可用部署,这个后面会讲。

1.3 作业提交:从零开始跑第一个任务

好,理论说完了,咱们直接上手。

你只需要一个命令:sbatch

先写一个最简单的作业脚本,我叫它 hello.slurm

#!/bin/bash
#SBATCH --job-name=my_first_job
#SBATCH --output=output_%j.txt
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=2
#SBATCH --mem=4G
#SBATCH --time=00:05:00

echo "Hello, SLURM!"
echo "当前节点是: $(hostname)"
sleep 30
echo "任务完成!"

然后提交:

sbatch hello.slurm

你会看到类似这样的输出:

Submitted batch job 12345

这个 12345 就是作业ID。记住它,后面监控、取消都要用它。

我的小习惯:作业脚本文件名我一般用 .slurm 后缀,方便区分。也有人用 .sh,都可以。但千万别用 .job —— 我见过有人用这个,结果被系统误判成别的格式,坑了自己。

1.4 作业监控:看看你的任务跑得怎么样了

提交完作业,你肯定想知道它跑没跑、跑在哪、跑多久了。

三个命令,记住就行:

  • squeue —— 查看队列状态
  • sacct —— 查看历史作业
  • scancel —— 取消作业

咱们一个个说。

squeue:实时队列

squeue -u 你的用户名

输出大概长这样:

JOBID  PARTITION  NAME     USER  ST  TIME  NODES  NODELIST(REASON)
12345  normal     my_first_job  zhang  R   0:32  1      node01
12346  gpu        gpu_job  li    PD  0:00  1      (Resources)

注意看 ST 这一列:

  • R = Running,正在跑
  • PD = Pending,排队中
  • CG = Completing,即将完成

我曾经遇到一个情况:作业一直PD,我以为是系统卡了。后来一查,是我申请了128G内存,但集群最大节点只有64G。嗯,这作业永远跑不了。所以资源申请要合理

sacct:历史记录

sacct -j 12345 --format=JobID,JobName,State,Elapsed,MaxRSS

这个命令特别有用。它能告诉你作业到底用了多少内存、跑了多久、有没有失败。

避坑指南:我曾经用 sacct 查一个作业,发现它显示 FAILED,但输出文件里全是正常日志。为什么?因为作业最后一步报错了,但前面的都成功了。所以一定要看 State,别只看输出文件。

scancel:取消作业

scancel 12345

就这么简单。如果你想取消所有自己的作业:

scancel -u 你的用户名

但小心,别手滑。我有个同事曾经在调试的时候,一个 scancel -u root 把全集群的作业都干掉了……嗯,那天他请全组喝了奶茶。

1.5 作业脚本编写规范:别让你的脚本变成「地雷」

写SLURM脚本,说白了就是写一个带「头信息」的bash脚本。但这个头信息,很多人写不好。

我总结了三条铁律:

  1. #SBATCH 必须写在脚本最前面,而且不能有空格
  2. 资源申请要精确,别多申请,也别少申请
  3. 输出路径要明确,别让日志散落一地

来看一个规范的例子:

#!/bin/bash
#SBATCH --job-name=my_job
#SBATCH --output=/home/zhang/logs/%x_%j.out
#SBATCH --error=/home/zhang/logs/%x_%j.err
#SBATCH --partition=normal
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=8
#SBATCH --cpus-per-task=1
#SBATCH --mem=16G
#SBATCH --time=02:00:00

# 加载环境
module load python/3.9

# 进入工作目录
cd /home/zhang/project

# 运行任务
python run.py --input data.txt --output result.txt

注意几个细节:

  • %x 会被替换成作业名,%j 替换成作业ID。这样日志文件不会重名。
  • --time 一定要写。不写的话,默认可能是无限时长,调度器会很难分配。
  • --partition 指定分区。不同分区可能有不同硬件,比如GPU分区、大内存分区。

我的经验:我见过最离谱的脚本,申请了 --mem=999999G。结果作业永远排不上队。你想想看,哪个节点有999T内存?所以资源申请要合理,先查一下集群配置:sinfo -o "%n %m %c" 可以看每个节点的内存和CPU。

1.6 本章知识体系总览

下面这张图,是我自己梳理的SLURM入门知识结构。你看一眼,心里就有谱了。

SLURM入门知识体系 三大核心组件 作业提交与监控 脚本编写规范 slurmctld - 中央控制器 slurmd - 节点守护进程 sacctmgr - 账户管理 「大管家 + 店长 + 财务」 sbatch - 提交作业 squeue - 查看队列 sacct - 历史记录 scancel - 取消作业 #SBATCH 头信息 资源申请要精确 输出路径要明确 时间限制必须写 核心原则:合理申请 + 规范脚本 + 及时监控 别让你的作业变成集群里的「地雷」 高通量计算从零到精通 · 第1章 理解组件 动手提交 规范脚本 持续监控

1.7 本章小结

这一章,咱们把SLURM的底子打好了。

  • 知道了SLURM是干什么的——说白了就是集群的「交通警察」
  • 理解了三大组件——大管家、店长、财务
  • 亲手提交了第一个作业——sbatch 没那么可怕
  • 学会了监控——squeuesacctscancel 三件套
  • 掌握了脚本规范——头信息、资源申请、输出路径

我个人觉得,学SLURM最忌讳的就是「眼高手低」。你光看文档不实操,永远记不住。我建议你现在就去集群上跑一个作业试试,哪怕只是打印一句 Hello。跑通了,你就入门了。

课后小练习:写一个SLURM脚本,申请4个CPU、8G内存,运行 sleep 60,然后用 squeue 观察它的状态变化。试试看能不能在它运行的时候用 scancel 取消它。


公众号:蓝海资料掘金营,微信deep3321