Skip to content

Slurm 学习路径:从装起来到能提交作业 ​

先说这张页面是什么:不是「Slurm 是什么」的科普,也不是又一篇安装教程。它是一张路标——把站内已经写好的五篇 Slurm 文章按实际动手顺序排成一条路,每一站给出目标、读哪篇、敲什么命令、怎么算通过。

如果你现在只想提交作业、不想碰集群,直接跳到 第三站。

三条起点,别从同一页开始 ​

你的处境从哪进为什么
手上有一批裸机,要搭一套能用的 Slurm第一站部署两篇(Rocky / Ubuntu)任选其一,按发行版走
集群已经有人搭好,你只是新接手第二站先学会「怎么看」再去改,别一上来动 slurm.conf
只要会提交和管理作业第三站前面两站对你是噪音

第一站:把控制面和计算面拉起来 ​

目标:slurmctld 与 slurmd 都处于 active,sinfo 能看到节点,节点不是 down。

读哪篇:按发行版二选一——Rocky Linux 9 全流程 或 Ubuntu 22.04 + Slurm 24.05。两篇的骨架一致,差别在包管理与 systemd 单元命名。

动作(顺序不要换,换了几何级增加排错成本):

  1. 先定主机名与解析,slurm.conf 里的 SlurmctldHost 必须是 hostname -s 能解释的名字;
  2. 统一 munge:所有节点同一把 /etc/munge/munge.key,属主 munge、权限 400。这是 Slurm 唯一的手工「信任根」,密钥不一致的表现是节点永远 down 而日志只说认证失败;
  3. 用 slurmd -C 生成节点行,而不是手抄 CPU/内存参数——它直接读本机实际值,能避免 RealMemory 写小导致作业被降级;
  4. 再起服务,最后才动 slurm.conf 里的调度策略。

验收:

bash
systemctl status slurmctld slurmd --no-pager | grep -E "Active|slurm"
sinfo -N -l                       # 每行一个节点,STATE 不能是 down/inval
scontrol show node node01 | grep -E "State|RealMemory|CfgTRES|Gres"

卡点:sinfo 里节点 down*,星号意思是「有人手动设的」。先看 sinfo -R 给出的原因,处理完再 scontrol update NodeName=node01 State=RESUME。没处理根因直接 RESUME,下一次心跳还会 down。

第二站:让节点真正可用(接手集群必读) ​

目标:节点 idle、GPU 能被识别为可分配资源、作业不会因为内存被系统杀掉。

读哪篇:Slurm 作业提交与管理指南 的前半部分,讲清了 sinfo/scontrol/squeue 的判读;配置侧看部署篇的 slurm.conf 章节。

必查的四件事:

检查点命令期望
GPU 是否被登记为 GRESscontrol show node node01 | grep Gres有 gpu:... 计数,不是空
可分配 CPU/内存sinfo -N -o "%N %c %m %e"%c 与实际核数一致
cgroup 是否生效scontrol show config | grep -E "ProctrackType|TaskPlugin"proctrack/cgroup + task/cgroup
计费是否落库sacct -a -n | head有记录;空则 slurmdbd 未接

关键参数(这六个改错会直接影响能不能用,其余保持默认即可):

ini
SelectType=select/cons_tres
SelectTypeParameters=CR_Core_Memory     # 允许按核+内存组合分配
GresTypes=gpu
ProctrackType=proctrack/cgroup
TaskPlugin=task/cgroup
DefMemPerCPU=4000                       # 按核给默认内存,避免 --mem 不写就无限制

SelectType 用 cons_tres(消费型可追踪资源)而不是老的 cons_res,是能否按「核 + 内存 + GRES」精细分配的前提。

第三站:提交第一个作业 ​

目标:能用 srun 交互跑一条命令,能用 sbatch 跑一个脚本,能用 squeue/scontrol 看出它在干什么。

读哪篇:Slurm 作业提交与管理指南。

最小可用序列:

bash
# 1) 一条命令的冒烟测试:2 节点 × 8 任务 × 每节点 1 卡
srun -N2 --ntasks-per-node=8 --gres=gpu:1 hostname

# 2) 语法检查,不真正排队(省掉「排了两小时才发现脚本有错」)
sbatch --test-only job.sbatch

# 3) 提交并盯住
sbatch job.sbatch
squeue -u "$USER" -o "%.10i %.20j %.10P %.2t %.10M %R"

一个能直接用的 job.sbatch 骨架:

bash
#!/bin/bash
#SBATCH -J train-demo
#SBATCH -p gpu
#SBATCH -N 2
#SBATCH --ntasks-per-node=8
#SBATCH --gres=gpu:1
#SBATCH --cpus-per-task=4
#SBATCH --mem=64G
#SBATCH -t 02:00:00
#SBATCH -o logs/%j.out
#SBATCH -e logs/%j.err

set -euo pipefail
module load cuda/12.4
srun python -u train.py --epochs 10

验收:作业从 PD 进到 R 再到 CD,sacct 能查到 Elapsed/ExitCode/MaxRSS。

bash
sacct -j <jobid> --format=JobID,JobName,Partition,Elapsed,State,ExitCode,MaxRSS

卡点:作业一直 PD 而不 R,八成不是排队,而是资源请求超过了单节点实际值(--mem 写 128G 但节点只有 120G,或者 --gres=gpu:2 但节点只登记了 1 卡)。此时 scontrol show job <id> 的 Reason 字段会直接告诉你原因。

第四站:把作业跑「对」而不只是跑「起来」 ​

目标:多节点任务分布符合预期、CPU 亲和性不乱跳、MPI 混合并行不空转。

读哪篇:Slurm + Docker 分布式训练提交模板 讲容器场景;MPI 部分见 MPI + Slurm 实战:作业调度与性能调优;同机多卡的通信上限见 集合通信原语与库。

三个高频错法:

症状根因修正
开了 16 个任务,但只有一个进程在算进程数由 --ntasks 决定,不是由 python 循环决定srun --ntasks=16,或用 --ntasks-per-node
MPI 程序卡在启动阶段mpirun 在 srun 里再套一层,任务重复展开二选一:Slurm 下用 srun ./app,或 mpirun 配 --bootstrap 系列参数
性能只有一半进程/线程在 NUMA 上漂移--cpu-bind=cores、OMP_NUM_THREADS=$SLURM_CPUS_PER_TASK

一个稳定的混合并行写法(每节点 2 个 MPI 进程 × 每进程 8 线程,绑核):

bash
srun --ntasks-per-node=2 --cpus-per-task=8 --cpu-bind=cores \
     bash -c 'export OMP_NUM_THREADS=$SLURM_CPUS_PER_TASK; ./solver'

验收:srun hostname | sort | uniq -c 的任务分布与请求一致;sacct 里 MaxRSS 不超过申请值;sstat -j <id> -a 能看到每个任务的实时 CPU 效率。

第五站:让环境可复现(容器化) ​

目标:同一个镜像在任意节点上跑出同一结果,且不需要 root。

读哪篇:HPC 集群容器化:Apptainer 的 SIF、GPU 注入与 Slurm 落地;需要 Docker 而不是 Apptainer 的场景看 基于 Docker 的分布式训练提交模板。

要点:容器在 Slurm 里只是「srun 后面那个命令」——srun apptainer exec --nv x.sif python train.py。真正要决策的是三件事:镜像放哪(别让 200 个节点同时拉同一份)、挂载哪些目录(--containall 会清掉默认绑定)、GPU 驱动代际是否与宿主一致。

验收:srun apptainer exec --nv x.sif nvidia-smi 在分配到的每张卡上都能出表,且卡号与 CUDA_VISIBLE_DEVICES 一致。

六、一次性通过的验收清单 ​

按顺序打勾,全部通过再对外说「集群可用」:

  • [ ] sinfo -N -l:所有节点 idle/mixed,无 down、无 inval
  • [ ] scontrol show node <n> | grep Gres:GPU 计数与实际一致
  • [ ] srun -N1 --ntasks=1 hostname:单节点冒烟通过
  • [ ] srun -N2 --ntasks-per-node=8 hostname:跨节点通过,任务数对得上
  • [ ] sbatch --test-only job.sbatch:语法与资源请求合法
  • [ ] 真实作业跑完,sacct 有 Elapsed/ExitCode/MaxRSS
  • [ ] 故意 scancel 一次,确认作业能被干净回收,不残留 CG 态
  • [ ] (可选)slurmdbd 接上,share/sshare 能看到账户权重
  • [ ] (可选)srun apptainer exec --nv x.sif nvidia-smi 通过

七、卡点速查 ​

现象先看这里一句话处置
节点 down,日志报认证失败munge 密钥与权限全节点同一把 key,属主 munge、400
sinfo 全 down*有人手动设过状态根因处理完再 scontrol update ... State=RESUME
作业长期 PDscontrol show job 的 Reason多半是资源请求超过节点实际配置
作业瞬间 FAILED,ExitCode 非零%j.errset -euo pipefail 让第一个错误就停
MaxRSS 超申请值cgroup 未生效ProctrackType/TaskPlugin 换成 cgroup 版
GPU 分到了但 nvidia-smi 报错驱动/容器代际容器内库版本要与宿主同代
slurmctld 起来又退slurmctld -Dvvv 前台跑一次配置解析错会直接打在第一屏

收口三句 ​

  • 顺序比技巧重要:主机名与密钥 → slurmd -C 生成节点行 → 起服务 → 再调策略,这个顺序错了,后面每一步都在给前面擦屁股;
  • sinfo/scontrol 是你的仪表盘:任何「作业不跑」的问题,答案几乎都在 Reason、State、Gres 这三个字段里;
  • 能验收才算搭完:srun 冒烟、sbatch --test-only、sacct 三件套跑通,比写满一页 slurm.conf 更有意义。

延伸阅读 ​

相关文章 ​

AI-HPC 智算超算专家 · Contact: openaihpc@gmail.com