十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Slurm作业调度系统核心命令详解:从sbatch到scancel实战指南

Slurm作业调度系统核心命令详解:从sbatch到scancel实战指南 1. 从零开始理解Slurm它是什么以及为什么你需要它如果你第一次接触高性能计算HPC或者大规模集群计算看到“Slurm”这个词可能会有点懵。它不是某种饮料也不是游戏里的角色而是一个在学术界和工业界被广泛使用的、开源的集群管理和作业调度系统。简单来说你可以把它想象成一个超级智能的“任务分配大师”。当你面对一个由成百上千台计算节点服务器组成的庞大集群时你不可能手动登录到每一台机器上去启动你的计算程序。Slurm就是那个帮你做这件事的“大管家”。它的核心工作流程是这样的你写好一个计算任务我们称之为“作业”告诉Slurm你需要多少计算资源比如需要多少CPU核心、多少内存、需要运行多久然后通过简单的命令把它提交给Slurm。Slurm的调度器会根据整个集群当前的负载情况、资源空闲状态以及预设的调度策略在合适的时机、将你的作业分配到最合适的计算节点上去执行。执行过程中你可以随时查看作业的状态执行完毕后Slurm会把计算结果输出到你指定的地方。整个过程你几乎不需要关心你的程序具体在哪台物理机器上运行这种体验对于大规模科学计算、AI模型训练、数据分析等场景来说是革命性的。我刚开始用Slurm的时候也觉得那一堆命令参数很头大。但用久了就会发现日常工作中真正高频使用的命令就那么十来个。掌握它们你就能丝滑地在集群上开展绝大部分工作了。这篇文章我就结合自己多年的使用和运维经验把这些最常用、最核心的Slurm命令给你掰开揉碎了讲清楚目标是让你看完就能上手避开我当年踩过的那些坑。2. 作业生命周期管理从提交到完成的完整链条一个作业在Slurm体系里的生命周期通常包括提交、排队、运行、完成或失败这几个阶段。对应的有一组命令专门用于管理这个链条。2.1 提交作业sbatch命令的深度解析sbatch是你最需要熟练掌握的命令没有之一。它的作用就是向Slurm提交一个作业脚本。这个脚本本质上是一个Shell脚本比如Bash但在脚本的开头需要用特定的格式注释以#SBATCH开头来告诉Slurm这个作业的资源需求。一个最基础的作业脚本my_job.sh可能长这样#!/bin/bash #SBATCH --job-nametest_job # 作业名方便识别 #SBATCH --outputslurm-%j.out # 标准输出重定向文件%j会被替换为作业ID #SBATCH --errorslurm-%j.err # 标准错误重定向文件 #SBATCH --partitioncompute # 指定提交到哪个分区队列 #SBATCH --nodes1 # 申请1个计算节点 #SBATCH --ntasks-per-node4 # 每个节点上运行4个任务可理解为进程 #SBATCH --cpus-per-task2 # 每个任务分配2个CPU核心 #SBATCH --mem8G # 每个节点申请8GB内存 #SBATCH --time01:00:00 # 作业运行最大时间限制格式时:分:秒 # 从这里开始是你真正的计算任务命令 echo “开始计算任务当前节点是hostname” # 假设你有一个并行计算程序叫 my_simulation srun ./my_simulation --input data.in --output result.out echo “计算任务完成”提交这个作业只需要sbatch my_job.sh提交成功后命令行会返回一个作业ID例如Submitted batch job 123456。这个ID就是你后续跟踪和管理这个作业的钥匙。这里有几个关键参数和避坑点--partition: 分区是集群资源的逻辑划分。比如可能有debug调试排队快但时间短、compute常规计算、bigmem大内存节点、gpuGPU节点等。一定要根据作业需求选择正确的分区否则可能无法调度或资源浪费。--nodes,--ntasks,--cpus-per-task,--mem: 这些是资源请求的核心。--nodes和--ntasks的关系需要理解--ntasks是你需要的总进程数。如果指定--nodes2 --ntasks8Slurm可能会在2个节点上各启动4个进程。--cpus-per-task是每个进程需要的CPU核心数。对于多线程程序如OpenMP这个值应该设为你需要的线程数。--mem默认是每个节点的内存总量。你也可以用--mem-per-cpu指定每个CPU核心的内存。这里最容易踩坑的是内存估计不足导致作业运行中被系统杀死OOM。建议根据程序历史运行峰值内存再增加20%-30%的余量。--time:这是最重要的参数之一直接影响作业调度优先级和能否运行。Slurm调度器倾向于优先调度短作业以提高资源周转率。如果你预估需要2小时可以设--time02:30:00留出缓冲。但切忌盲目设得过大比如一周这会导致作业在队列中等待很久因为调度器在寻找能连续满足你时间窗的空闲资源。对于不确定时间的探索性任务可以先设一个较短时间用后面会讲到的scontrol命令在运行时延长。输出重定向--output和--error非常有用。%j通配符会自动替换为作业ID这样不同作业的输出就不会相互覆盖。我习惯加上时间戳如slurm-%j-%N.out%N是节点名便于追溯。除了写脚本sbatch也支持通过命令行参数直接提交例如sbatch --job-namecli_test --time00:10:00 script.sh。命令行参数会覆盖脚本中#SBATCH的相同设置。这在快速测试时很方便。2.2 交互式作业srun与salloc的适用场景有时候你不想写脚本只是想快速登录到一个计算节点上做一些交互式操作比如调试代码、安装软件、测试小任务。这时就需要交互式作业。srun: 最直接的交互式运行命令。它直接申请资源并运行一个命令。# 申请一个节点上的一个任务交互式运行一个shell srun --partitiondebug --nodes1 --ntasks1 --time00:30:00 --pty /bin/bash执行后如果你的资源请求得到满足当前终端就会“跳转”到分配的计算节点上你可以像在本地一样操作。退出bash资源即被释放。srun也用于在作业脚本内部启动并行任务如前例所示这是MPI等并行程序在Slurm环境下的标准启动方式。salloc: 分配资源并返回一个“作业”。它先为你分配资源此时作业状态是RUNNING但不会立即跳转到节点。你需要手动ssh到分配到的节点上去工作。# 申请资源 salloc --partitioncompute --nodes2 --ntasks-per-node4 --time01:00:00 # 命令返回salloc: Granted job allocation 123457 # 查看分配到了哪些节点 scontrol show job 123457 | grep NodeList # 输出可能 NodeListnode[101-102] # 然后手动登录到其中一个节点例如 node101 ssh node101salloc更适合这样的场景你需要一个持久化的资源分配可能在其中多次登录、运行多个相关任务或者启动一个复杂的、需要多个步骤交互的环境比如某些图形化调试工具。所有任务完成后需要用scancel命令后面会讲来释放资源。选择建议快速单次调试用srun --pty bash需要更灵活、更持久的交互会话用salloc。2.3 监控作业状态squeue命令的多维度视图作业提交后最关心的问题就是“我的作业排到哪了在运行吗”squeue就是你的“作业状态监视器”。最基本的用法是查看所有作业squeue输出类似JOBID PARTITION NAME USER ST TIME NODES NODELIST(REASON) 123456 compute test_job alice R 0:05 1 node101 123457 debug interact bob PD 0:00 2 (Resources) 123458 compute long_sim charlie R 2:30 4 node[201-204]几个关键列ST状态: 这是最重要的信息。R(RUNNING): 正在运行。PD(PENDING): 排队中。括号里会给出排队原因最常见的是(Resources)等待资源可用、(Priority)优先级不够、(Dependency)等待依赖的作业完成。CG(COMPLETING): 正在完成清理阶段。F(FAILED),TO(TIMEOUT) 等表示作业异常结束。NODELIST(REASON): 对于运行中的作业显示节点列表对于排队中的作业显示排队原因。TIME: 作业已运行的时间。squeue有大量过滤选项来聚焦你的信息squeue -u $USER: 只看你自己提交的所有作业。squeue -p compute: 只看compute分区的作业。squeue --statesRUNNING: 只看正在运行的作业。squeue -j 123456,123457: 查看指定作业ID的详情。squeue --start:一个非常有用的命令它会估算你的排队作业预计何时能够开始运行。这对于规划工作非常有帮助。我个人的习惯是设置几个别名alias在~/.bashrc里alias myq“squeue -u $USER -o \”%.18i %.9P %.30j %.8u %.2t %.10M %.6D %R\“” alias qall“squeue -o \”%.18i %.9P %.30j %.8u %.2t %.10M %.6D %R\“”这样myq就能以更紧凑、信息更集中的格式查看自己的作业了。格式控制符%.18i等可以自定义输出列宽和内容具体可以查squeue的 man page。2.4 探查作业详情scontrol show job与sacct的对比当squeue提供的信息不够时我们需要更详细的“体检报告”。scontrol show job jobid: 用于查看正在运行或排队中的作业的实时、最详细信息。这是调试作业问题的一把利器。scontrol show job 123456输出信息极其丰富包括作业提交时间、开始时间、时间限制。详细的资源请求CPU、内存、节点特征等。实际分配到的节点列表。工作目录、提交的脚本路径。作业依赖关系、用户ID、组ID等。 当你发现作业状态异常比如一直Pending仔细查看scontrol的输出尤其是结尾部分常常会给出具体原因例如不满足某个节点的特定特征比如需要某个特定的软件许可证。sacct: 用于查看已完成无论成功失败作业的会计信息。它的视角是历史记录。# 查看今天自己所有作业的概况 sacct --formatJobID,JobName,Partition,Account,AllocCPUS,State,ExitCode,Elapsed,MaxRSS -u $USER--format参数至关重要用于指定显示哪些列。上面例子显示了作业ID、名、分区、账户、分配的CPU数、最终状态、退出码、运行时长和最大常驻内存MaxRSS。MaxRSS是黄金信息它告诉你作业实际消耗的最大物理内存。对比你申请的内存--mem就能知道你的内存预估是否准确为下次提交作业提供精准依据。可以按时间过滤--starttime2024-01-01 --endtime2024-01-02。可以查看某个特定作业的详细信息sacct -j 123456 --formatJobID,JobName,State,ExitCode,MaxRSS,NodeList。核心区别与选择看实时状态、找排队/运行中作业的问题根源用scontrol show job。看历史记录、分析作业资源使用效率特别是内存、统计工作量用sacct。2.5 终止作业scancel的精准操作发现作业提交错了或者程序陷入死循环就需要手动终止它。scancel jobid: 终止一个特定作业。scancel -u $USER:危险命令终止你自己所有的作业包括排队和运行的。使用前务必三思。scancel --statePENDING -u $USER: 只终止自己所有排队中的作业保留正在运行的。这在批量提交测试作业后清理队列时很实用。scancel --signalUSR1 jobid: 不直接杀死作业而是向它发送一个USR1信号。你可以在自己的程序里捕获这个信号做一些优雅的清理工作比如保存中间结果后再退出。这比粗暴的SIGKILL友好得多。3. 集群资源洞察了解你的“战场”高效使用集群不仅要知道如何提交作业还要清楚集群当前有多少“兵力”资源可用这样才能提出合理的资源请求。Slurm提供了一系列资源查询命令。3.1 查看节点状态sinfo命令的实用技巧sinfo给你一个集群节点状态的全局视图。sinfo典型输出PARTITION AVAIL TIMELIMIT NODES STATE NODELIST compute* up infinite 8 idle node[101-108] compute* up infinite 2 alloc node[109-110] gpu up 3-00:00:00 4 idle gpu[001-004] debug up 01:00:00 2 idle debug[01-02] debug up 01:00:00 1 drain debug03PARTITION: 分区名。后面的*表示这是默认分区。AVAIL: 分区是否可用up/down。TIMELIMIT: 该分区上作业的最大运行时间限制。infinite表示无限制通常有隐含限制。STATE: 节点状态。idle: 节点空闲可用。alloc: 节点已被分配正在运行作业。mix: 节点部分资源被分配比如有32个核心其中16个正在用。drain: 节点正在排水维护状态不接收新作业但正在运行的作业可以继续。down: 节点故障或下线。NODELIST: 处于该状态的节点列表。常用过滤选项sinfo -p compute,gpu: 只看指定分区。sinfo -N: 以节点为单位列出信息更详细。sinfo -R: 列出所有状态非idle的节点及其原因例如为什么drain。sinfo --Node --statesidle: 列出所有空闲节点的详细信息在需要手动选择节点进行交互式测试时有用。3.2 深入节点详情scontrol show nodesinfo是列表视图scontrol show node则是单个节点的详情页。当你想知道一个节点具体配置比如有多少CPU、多大内存、有哪些特殊特性如GPU型号时就用这个命令。scontrol show node node101输出会包括CPU架构、核心数、线程数。真实内存和可用内存大小。临时磁盘空间/tmp。节点权重用于调度。Features特性: 这是Slurm一个非常强大的功能。管理员可以给节点打上标签比如skylake,avx512,a100,nvlink。你在提交作业时可以通过--constraint参数指定需要的特性调度器就会把你分配到满足条件的节点上。例如sbatch --constraint“a100” ...。3.3 查看用户资源使用sshare与squeue结合在多用户共享的集群中公平性很重要。Slurm通常配置了公平分享Fairshare策略你的作业优先级不仅取决于作业本身还取决于你和你所在组的历史资源使用情况。sshare: 查看用户的公平份额信息。输出包括账户、用户名、当前份额Raw Shares、最近使用量Raw Usage和计算出的有效份额Effectv Usage。有效份额越低通常意味着你近期的资源消耗越少下一个作业的优先级可能会更高。这解释了为什么有时候你的小作业要排很久的队——可能你或你的组最近“吃”了太多资源。squeue -u $USER --start: 如前所述结合--start参数可以预估作业开始时间帮助你判断是资源紧张还是自己优先级低。理解这些信息有助于你合理安排大型作业和中小型作业的提交节奏避免“资源饥荒”。4. 高级功能与实战技巧提升你的集群使用效率掌握了基本命令就像学会了开车。但要开得又快又稳还需要一些高级技巧和实战经验。4.1 作业依赖构建自动化工作流很多计算任务不是独立的而是有前后依赖关系的。比如任务B需要等任务A的输出文件作为输入。你可以手动等A完成再提交B但更优雅的方式是使用作业依赖--dependency。# 提交作业A JOBID_A$(sbatch job_A.sh | grep ‘Submitted’ | awk ‘{print $4}’) echo “Job A ID is: $JOBID_A” # 提交作业B并指定依赖关系等A成功完成状态为COMPLETED后再运行 sbatch --dependencyafterok:$JOBID_A job_B.sh # 其他常见的依赖类型 # afternotok: A失败后运行B # afterany: A结束后无论成功失败运行B # singleton: 同一时间只允许一个具有此标签的作业运行用于互斥任务这样Slurm会自动帮你管理依赖链。你可以构建复杂的流水线比如预处理 - 并行计算 - 后处理全部通过依赖关系串联起来实现工作流的自动化。4.2 数组作业海量参数扫掠的利器如果你需要运行同一个程序只是输入参数或输入文件不同例如对100个不同的初始条件进行模拟为每一个都写一个作业脚本就太蠢了。数组作业Job Array就是为此而生。# 在作业脚本中 #SBATCH --array1-100%10 # 这表示创建索引从1到100的作业数组但同时最多运行10个%10用于控制并发避免瞬间塞满队列 # 在脚本内部可以通过环境变量 SLURM_ARRAY_TASK_ID 获取当前数组任务的索引 INPUT_FILE“input_${SLURM_ARRAY_TASK_ID}.dat” OUTPUT_FILE“output_${SLURM_ARRAY_TASK_ID}.dat” ./my_program -i $INPUT_FILE -o $OUTPUT_FILE提交后你会得到一个作业ID如123456_1表示数组作业的母作业而squeue会显示123456_[1-100]。你可以用scancel 123456_[1-50]取消前50个子任务管理起来非常方便。sacct查看时也会区分每个子任务的状态和资源使用。4.3 运行中作业的调整scontrol update作业提交后发现参数设错了怎么办比如时间估计不足作业快要被超时杀死了。Slurm允许在作业运行期间修改部分参数。# 延长作业123456的时间限制增加2小时 scontrol update jobid123456 TimeLimit02:00:00 # 修改作业名称便于识别 scontrol update jobid123456 JobName“new_cool_name”注意不是所有参数都能修改通常TimeLimit,JobName,--mail-user等是可以的但像节点数、核心数等资源请求一般不能在运行中更改。具体请查阅文档或咨询管理员。4.4 环境变量与信息传递在脚本中获取Slurm信息Slurm会在作业运行时设置一系列环境变量你的脚本可以利用它们实现更灵活的控制。#!/bin/bash # 常用环境变量示例 echo “本作业ID: $SLURM_JOB_ID” echo “本作业在数组中的索引如果是数组作业: $SLURM_ARRAY_TASK_ID” echo “分配到的节点列表: $SLURM_JOB_NODELIST” echo “当前节点的主机名: $SLURM_SUBMIT_HOST” echo “提交目录: $SLURM_SUBMIT_DIR” echo “本任务在本次作业中的本地ID: $SLURM_LOCALID” echo “本任务在全局的ID: $SLURM_PROCID” # 对于MPI任务非常有用 # 基于节点列表可以做一些复杂的设置例如为每个节点生成不同的配置文件 NODE_LIST$(scontrol show hostnames $SLURM_JOB_NODELIST) for NODE in $NODE_LIST; do ssh $NODE “echo ‘Node-specific config for $NODE’ /tmp/config_$NODE” done4.5 实用脚本与别名打造你的效率工具箱把常用操作封装成脚本或Shell别名能极大提升效率。快速提交测试作业脚本(qtest.sh):#!/bin/bash # 一个快速提交1节点、1核心、10分钟调试作业的脚本 sbatch --job-namequick_test \ --partitiondebug \ --nodes1 \ --ntasks1 \ --cpus-per-task1 \ --mem1G \ --time00:10:00 \ --outputtest_%j.out \ --wrap“echo ‘Hello from Slurm!’; hostname; sleep 30” # --wrap 参数可以直接运行命令字符串无需单独写脚本文件极其实用查看自己作业的详细状态(myjobalias):alias myjob‘function _myjob(){ squeue -u $USER -o “%.18i %.9P %.35j %.8u %.2t %.10M %.6D %R” -S “-t” | head -20; };_myjob’一键清理所有排队作业(谨慎使用):alias cancelpending‘scancel --statePENDING -u $USER’把这些脚本和别名放到你的~/.bashrc文件中每次登录集群就能直接使用。5. 避坑指南与最佳实践来自运维视角的经验之谈最后这部分分享一些我作为使用者和旁观者看过太多用户案例总结的“血泪教训”希望能帮你少走弯路。5.1 资源请求的“艺术”宁多勿少但忌盲目CPU核心数如果你的程序是纯MPI并行多进程--ntasks就是进程数。如果是多线程如OpenMP--cpus-per-task应设为线程数并且通常--ntasks1。如果是混合并行MPIOpenMP则需要仔细规划--ntasks和--cpus-per-task的乘积等于你需要的总CPU数。内存这是作业失败最常见的原因之一。务必使用sacct查看历史作业的MaxRSS并以此为基础增加安全余量。对于未知的新程序可以先用一个很小的输入在调试队列跑一下观察其内存使用峰值。时间时间估计不足会导致作业在即将出成果时被强制终止前功尽弃。时间估计过长则会严重降低作业调度优先级。一个策略是对于长时间作业可以设置一个“检查点”Checkpoint机制让程序定期保存状态。这样即使作业超时也可以从最后一个检查点重启只需重新提交一个从检查点开始的新作业即可。5.2 理解排队原因从squeue和scontrol中找答案当作业一直处于PD状态时别干等着。用squeue -j jobid看REASON列再用scontrol show job jobid看详细信息。(Resources): 最普遍的原因就是当前没有满足你资源需求的节点。可能是你要的节点数太多或者内存要求太高或者要求的GPU类型紧缺。考虑是否可以调整资源请求或者换一个资源需求低的时间段提交。(Priority): 你的作业优先级太低。可能是因为你的公平份额Fairshare值太低近期用了太多资源或者作业时间请求太长。对于短作业可以尝试提交到debug这类高优先级队列。(Dependency): 在等待依赖的作业完成。检查你依赖的作业状态。(PartitionDown),(NodeDown): 指定的分区或节点下线了。联系管理员或换分区。5.3 I/O性能与共享文件系统集群计算节点通常通过网络共享存储如NFS、Lustre。你的作业从共享目录读取输入文件并向共享目录写入输出。避免大量小文件读写这会对元数据服务器造成巨大压力拖慢整个系统。尽量将小文件打包或使用数据库等更适合的存储方式。使用节点本地存储/tmp或$SLURM_TMPDIR如果作业需要频繁读写临时文件一个最佳实践是在作业开始时将输入文件从共享存储复制到节点的本地临时目录环境变量$SLURM_TMPDIR指向的就是每个作业独立的本地临时空间计算过程全部在本地进行计算结束后再将最终结果文件复制回共享存储。这能极大减轻共享存储的压力并提升作业的I/O性能。输出文件管理养成好习惯在作业输出目录中以作业ID或时间戳创建子目录避免文件混乱。在作业脚本开头使用mkdir -p $SLURM_SUBMIT_DIR/outputs/$SLURM_JOB_ID并在此目录下工作。5.4 与管理员有效沟通当你遇到无法解决的问题时需要联系集群管理员。提供有效信息能帮你更快获得帮助完整的作业ID。你使用的完整sbatch命令或作业脚本。错误现象从哪个命令看到什么错误信息。你已经尝试过的排查步骤例如用scontrol show job看到了什么。相关的日志文件内容slurm-jobid.out和.err文件。记住管理员喜欢看到用户已经做了一些基础的排查工作这能大大提升沟通效率。掌握这些命令和技巧你就能从Slurm的“新手用户”进阶为“高效用户”。集群计算的核心思想是资源管理和任务调度Slurm是实现这一思想的优秀工具。理解它的逻辑善用它的命令就能让强大的计算资源真正为你所用加速你的科研和工程探索。
返回列表