
简介这份《国科大超算中心Slurm作业调度系统使用指南》面向高性能计算初学者与科研人员聚焦超算集群中作业提交与资源调度的实际问题帮助读者快速掌握Slurm调度系统的核心用法。资源为1个PDF文件压缩包约595KB篇幅紧凑、便于随查随用。内容从基本概念与三种模式区别讲起依次覆盖sinfo查看队列与节点、squeue查看作业、scontrol show partition/node/job查看详细分区、节点与作业信息并系统讲解srun交互式提交、sbatch批处理提交、salloc分配式提交三类作业方式涵盖串行、OpenMP共享内存、MPI并行及GPU作业的提交示例还涉及IO重定向、环境变量、sbcast文件同步与sattach作业步吸附等进阶操作。目前已有3353人学习适合需要在中国科大超算或同类Slurm集群上跑通并行程序的用户对照查阅目录结构清晰可作为日常提交作业与排错的实用手册。1. 从登录节点到计算节点一份被低估的 Slurm 实战手册很多刚接触高性能计算的人第一次拿到超算账号后最容易犯的错就是在登录节点上直接敲./run.sh。程序确实跑起来了但整个集群的登录响应瞬间变慢管理员找上门只是时间问题。这份《Slurm 作业调度系统使用指南》解决的正是这个断层——它不讲调度器源码而是把sinfo、squeue、sbatch、srun、salloc这些命令拆成可查、可抄、可排错的条目。它适合三类人刚拿到超算账号、需要把本地程序搬上集群的研究生从 PBS/Torque 迁移过来、需要快速对照命令差异的工程师以及需要给团队写内部上机规范的技术负责人。手册基于 Slurm 19.05.5 编写覆盖队列查询、作业提交、环境变量、记账与作业管理是一份能直接放在手边翻的速查资料。2. 三种提交模式怎么选sbatch、srun 与 salloc 的边界2.1 批处理、交互式与分配式的本质差异Slurm 把作业提交分成三条路径选错模式是新手最常见的翻车点。手册里把三者并列讲但实际使用时判断逻辑很简单看你的任务需不需要人在终端前盯着。批处理模式用sbatch提交脚本命令立即返回作业进入队列等待调度。脚本被调度后在分配到的首个节点上执行。关键特性是提交终端的生命周期与作业无关——你关掉 SSH作业照跑。这是生产环境跑长任务的标准姿势。交互式模式用srun资源分配和任务加载两步合一。你在登录 shell 里敲下srun它会先向slurmctld申请资源拿到后再在分配节点上启动任务。这个过程中你的终端被占住任务不结束你回不到提示符。更麻烦的是如果提交时那个终端断了任务直接终止。所以它只适合短时间调试比如验证一个 MPI 程序能不能正常初始化。分配式模式用salloc本质是前两者的融合。你先用salloc申请资源Slurm 把资源分配给你后在提交节点上执行你指定的命令——通常就是启动一个 shell。然后你在这个 shell 里用srun跑并行任务。salloc和sbatch最核心的区别在于任务执行位置salloc在提交作业的节点执行sbatch在分配的第一个计算节点执行。这个差异决定了salloc适合需要指定运行节点、边调边改的场景。提示登录节点只做编译和轻量文件操作。任何计算任务哪怕只跑三秒也走提交命令。2.2 用 sinfo 摸清家底再提交选模式之前得先知道集群有什么。sinfo是查看队列和节点状态的第一命令但很多人只用默认输出漏掉了关键信息。# 查看所有队列的详细状态包括不可用队列 sinfo -a -l # 只看 GPU 队列按节点名排序 sinfo -p GPU-V100 -N -S N # 持续每 5 秒刷新观察节点状态变化 sinfo -i 5 # 只看宕机或失去活力的节点并显示原因 sinfo -R第一行-a会显示隐藏队列有些集群把特定队列配置为对部分用户组隐藏不加这个参数你根本看不到。-l输出长格式包含TIMELIMIT、JOB_SIZE、NODES等字段。第二行-N让每个节点占一行-S N按节点名升序排列排查特定节点时比默认的聚合视图有用得多。第三行-i 5进入轮询模式适合盯着一个刚提交的作业看它什么时候从idle变allocated。第四行-R显示不可用节点的原因比如Not responding或Low disk space比只看状态码直观。输出里的STATE字段值得单独记idle表示空闲可接新作业mixed表示节点在跑作业但还有空闲核allocated表示全部分配完down和drained都不可用但原因不同——down通常是硬件或服务挂了drained是管理员主动排空。如果状态后面带*说明节点没响应这时候提交上去也是白等。2.3 squeue 看作业卡在哪作业提交后不运行第一反应是squeue看状态。默认输出只有JOBID、PARTITION、NAME、USER、ST、TIME、NODES、NODELIST(REASON)几列但REASON字段才是排错入口。# 查看当前用户的所有作业显示完整原因 squeue -u $USER -o %.10i %.9P %.20j %.8u %.2t %.10M %.6D %R # 只看排队中的作业按提交时间排序 squeue -t PD -S i # 查看特定作业号的详细信息 squeue -j 12345 --start第一行用-o自定义输出格式%R展开为完整的NODELIST(REASON)。常见的REASON有Resources表示资源不够等就完了Priority表示有更高优先级的作业在前面Dependency表示在等依赖作业结束QOSMaxCpuPerUserLimit表示你用的 QOS 限制了单用户 CPU 数这时候加节点也没用得换队列或等。第二行-t PD过滤出排队中的作业-S i按提交时间升序能看出是不是有作业被插队。第三行--start会估算一个预计开始时间虽然不一定准但能判断是等几分钟还是等几天。注意squeue默认只显示当前用户的作业。要看全队列用squeue -a但输出会很长建议配合-p指定队列。3. 从 sbatch 脚本到环境变量把作业写对3.1 一个能跑的 sbatch 脚本长什么样手册里把串行、OpenMP、MPI、GPU 作业分开讲但实际写脚本时结构是统一的。下面这个模板覆盖了最常用的指令块可以直接改。#!/bin/bash #SBATCH --job-namemy_sim # 作业名squeue 里显示 #SBATCH --partitionCPU-Large # 队列名用 sinfo 查到的 #SBATCH --nodes2 # 节点数 #SBATCH --ntasks-per-node32 # 每节点任务数通常等于 CPU 核数 #SBATCH --time24:00:00 # 墙上时间限制超时会被杀 #SBATCH --output%j.out # 标准输出%j 自动替换为作业号 #SBATCH --error%j.err # 标准错误 #SBATCH --mem64G # 每节点内存 module load intel/2019 # 加载编译器和 MPI module load openmpi/4.0.1 cd $SLURM_SUBMIT_DIR # 回到提交目录默认就在这但显式写更稳 srun ./my_mpi_program # 用 srun 启动并行任务#SBATCH开头的行是给调度器的指令不是 shell 注释。--nodes和--ntasks-per-node的乘积是总任务数MPI 程序里MPI_Comm_size拿到的就是这个值。--time格式是天-小时:分钟:秒只写24:00:00表示 24 小时。--output和--error里的%j是占位符Slurm 会替换成实际作业号避免多次提交互相覆盖。$SLURM_SUBMIT_DIR是 Slurm 注入的环境变量指向你敲sbatch时所在的目录脚本里cd过去能保证相对路径正确。提交命令就是sbatch run.sh返回一行Submitted batch job 12345。之后用squeue -j 12345看状态用scancel 12345取消。3.2 环境变量Slurm 注入的与用户导出的Slurm 在作业运行时注入一批环境变量脚本里可以直接用。手册里列了输入和输出两类实际高频使用的有这些变量名含义典型用途SLURM_JOB_ID作业号日志文件名、结果目录命名SLURM_JOB_NODELIST分配的节点列表传给 MPI 启动器或自定义脚本SLURM_NTASKS总任务数校验 MPI 进程数是否符合预期SLURM_CPUS_PER_TASK每任务 CPU 核数OpenMP 设置OMP_NUM_THREADSSLURM_SUBMIT_DIR提交目录脚本开头cd过去SLURM_JOB_PARTITION队列名条件判断走不同分支用户自己导出的变量默认不会传给计算节点除非用--export显式指定。比如你在登录节点export MY_DATA/home/user/data脚本里直接$MY_DATA会拿到空值。正确做法是在脚本里重新export或者提交时加--exportALL,MY_DATA。手册里还提到--exportNONE可以清空所有环境变量适合需要干净环境的场景但用之前确认脚本不依赖任何外部变量。3.3 srun 与 sbatch 的配合方式sbatch脚本里可以嵌srun这是 MPI 作业的标准写法。srun在作业分配的资源范围内启动任务Slurm 负责把进程分布到各节点。一个容易踩的坑是脚本里写mpirun -np 64 ./prog也能跑但绕过了 Slurm 的进程管理作业结束时可能残留孤儿进程。用srun ./prog则由 Slurm 统一管理生命周期scancel时能干净地杀掉所有 rank。如果作业里有多个可执行文件需要按顺序跑可以写多个srun每个srun是一个 job step。squeue默认只显示 job 级别加-s才能看到 step。scontrol show job jobid会列出该作业下所有 step 的状态和资源占用。4. 避坑与排查那些手册不会明说的翻车点4.1 作业一直 PDREASON 显示 Resources现象squeue看到作业状态PDNODELIST(REASON)显示Resources等了很久不动。原因请求的资源超过了队列当前空闲量。比如队列只有 10 个空闲节点你申请 20 个调度器不会给你排队等而是直接标记资源不足。另一个可能是--mem设得太大单节点内存不够。解决先用sinfo -p 队列名看空闲节点数和单节点配置。如果确实资源不够要么减少--nodes或--ntasks要么换到资源更充裕的队列。如果内存是瓶颈用sinfo -o %n %m %e看各节点总内存和空闲内存调整--mem到合理值。别盲目加--time时间限制和资源可用性无关。4.2 作业运行中突然消失没有输出文件现象squeue里作业不见了--output指定的文件不存在或为空sacct显示状态FAILED或NODE_FAIL。原因常见有三种。一是脚本第一行#!/bin/bash写错或缺失Slurm 用默认 shell 执行导致语法错误。二是cd $SLURM_SUBMIT_DIR之前就引用了相对路径的文件而作业的工作目录不是提交目录。三是节点故障NODE_FAIL表示分配到的节点在运行中挂了。解决先看sacct -j jobid --formatJobID,State,ExitCode,DerivedExitCode拿到退出码。ExitCode非零说明程序自身报错去.err文件里找堆栈。DerivedExitCode能区分是程序退出还是被信号杀死。如果是NODE_FAIL重新提交即可Slurm 会把作业重新调度到健康节点。脚本开头加set -e让错误立即暴露别让脚本带着错误往下跑。4.3 GPU 作业提交后报错找不到设备现象sbatch脚本里写了#SBATCH --gresgpu:1但程序启动时报CUDA error: no CUDA-capable device is detected。原因--gres只是向调度器申请 GPU 资源不会自动设置CUDA_VISIBLE_DEVICES。如果集群的 GPU 节点上有多块卡Slurm 会通过环境变量告诉进程该用哪块但前提是程序能读到这个变量。有些老版本 MPI 或自定义启动脚本会覆盖这个变量。解决在脚本里显式打印echo $CUDA_VISIBLE_DEVICES确认值是否被设置。如果为空检查sbatch提交时是否带了--gres以及队列是否配置了 GPU 资源。如果值正确但程序仍报错在srun前加export CUDA_VISIBLE_DEVICES$CUDA_VISIBLE_DEVICES强制传递。手册里 GPU 作业部分提到--gresgpu:1的写法但没展开环境变量传递链这是实际使用中最容易卡住的地方。4.4 scancel 杀不掉作业进程残留现象scancel jobid执行后squeue里作业消失但ssh到计算节点ps aux | grep 用户名还能看到进程在跑。原因scancel默认发送SIGTERM程序如果捕获了这个信号但不退出或者 MPI 进程之间的通信层没正确传播信号就会残留。另一种情况是作业脚本里用了后台启动进程Slurm 只管理前台进程。解决用scancel --signalKILL jobid强制发SIGKILL。如果还不行scontrol show job jobid拿到节点列表逐个ssh上去手动kill -9。预防措施是在脚本里用trap捕获SIGTERM并清理子进程或者避免在sbatch脚本里用启动需要随作业结束而终止的进程。5. 进阶用 sacct 做记账分析与作业调优作业跑完不是终点。sacct是 Slurm 的记账命令能拿到每个作业的实际资源消耗用来调优下一轮提交。默认sacct只显示当天作业加-S指定开始时间才能查历史。# 查看指定作业的详细资源使用 sacct -j 12345 --formatJobID,JobName,Partition,AllocCPUS,ReqMem,MaxRSS,Elapsed,State # 查看某天之后所有失败作业 sacct -S 2024-01-01 -s FAILED --formatJobID,JobName,State,ExitCode # 按队列统计作业数量和总核时 sacct -S 2024-01-01 -o Partition,AllocCPUS,Elapsed --parsable | awk -F| {print $1, $2, $3}第一行里MaxRSS是作业实际使用的最大常驻内存单位通常是 KB 或 MB。如果你申请了--mem64G但MaxRSS只有8G下次可以降到16G减少资源浪费也更容易排到队。Elapsed是实际运行时间对比--time限制能看出是不是经常超时。第二行-s FAILED过滤失败作业ExitCode字段格式是退出码:信号比如1:0表示程序返回 10:9表示被信号 9 杀死。第三行用--parsable输出管道分隔的格式方便awk做统计。我自己的习惯是每个作业跑完后跑一遍sacct -j jobid --formatJobID,MaxRSS,Elapsed,State把MaxRSS和申请值对比。如果实际内存不到申请的一半下次提交就砍掉冗余如果Elapsed接近--time限制说明时间设紧了下次加 20% 余量。这个动作花不到十秒但能显著提高排队效率。还有一个容易忽略的点sacct默认只显示父作业不显示 job step。加-X可以只看父作业汇总加-a显示所有 step。排查 MPI 作业里哪个 rank 先挂时sacct -j jobid -a --formatJobID,State,ExitCode能定位到具体 step。从那以后我每次提交长作业前都会先用sinfo确认目标队列的空闲节点和内存再跑一个短时间的srun测试脚本验证环境变量和模块加载最后才sbatch正式提交。这套流程走下来因为资源申请不当或环境问题导致的失败少了一大半。希望帮到你。本文还有配套的精品资源点击获取