1、集群队列管理概述:什么是作业调度系统、常见的调度器对比(SLURM、PBS、LSF)、集群资源管理的基本概念

刚接触高性能计算集群的朋友,第一次登录上来往往一脸懵:

「我明明有 256 个核,为什么 job 跑不起来?」
「别人提交的任务怎么插到我前面去了?」

嗯,这背后其实藏着一个关键角色——作业调度系统。说白了,它就是集群的「交通指挥员」,决定了谁先上车、走哪条道、用多少座位。

什么是作业调度系统

作业调度系统(Job Scheduler)的核心职责就三件事:

  • 资源分配——把 CPU、内存、GPU 这些硬件资源分给任务
  • 任务排队——按优先级、资源需求、用户策略决定执行顺序
  • 作业生命周期管理——从提交到运行到清理,全程接管

我记得早期帮某研究所搭集群时,用户直接 ssh 到计算节点手动跑程序,结果一个占满内存的进程把整个节点搞挂了。调度系统就是来治这种乱象的——让你别手贱,把资源管理交给机器。

一句话总结:没有调度系统的集群就是一盘散沙,谁抢到谁用,谁也保证不了稳定性。

常见调度器对比:SLURM、PBS、LSF

市面上主流的调度器就这三家。我三个都用过,也吃过不少苦头,这里直接上干货对比表。

特性 SLURM PBS (Torque/Moab) LSF
开源/商业 完全开源,GPL 开源核心 + 商业扩展 商业软件(IBM)
配置复杂度 中低,学起来快 中等,插件多 较高,依赖商业服务
可扩展性 极强,Top500 中大量使用 一般,万核以上吃力 强,适合大型企业
作业提交命令 srun, sbatch, squeue qsub, qstat, qdel bsub, bjobs, bkill
GPU 管理 原生支持,非常成熟 需要额外配置 支持,但依赖版本
典型用户 学术、HPC 中心、AI 训练 老牌超算中心 金融、制造、企业 IT

我个人习惯:新项目无脑选 SLURM。为什么?你想想看,现在 AI 训练几乎都是 SLURM + Kubernetes 的组合,社区活跃、文档全,遇到坑也能搜到答案。PBS 我在十多年前用过,那时候还是 Torque 的天下,后来慢慢被 SLURM 替代了。LSF 嘛,我在某大型药企见过,稳定是稳定,但一套 license 贵得离谱,小团队真用不起。

我的建议:如果团队小、预算有限,直接上 SLURM;如果公司有钱且有 IBM 生态绑定,LSF 也不是不能选。但记住,千万别自己魔改调度器——我曾经见一个团队在 PBS 上加了乱七八糟的插件,最后升级时全部废掉,血泪教训。

集群资源管理的基本概念

要玩转调度器,这几个概念你必须吃透。它们就像交通规则里的红绿灯、车道和限速牌。

节点(Node)

集群里的每一台物理机或虚拟机就是节点。节点分两种:

  • 登录节点——你 ssh 上来写脚本、提交作业的地方,别在这跑计算
  • 计算节点——真正干活的地方,调度器帮你把任务塞进去

我在项目中遇到过有人把深度学习训练直接跑在登录节点上,结果整个集群 200 多号人卡死了——嗯,后来我加了个 cgroup 限制才解决。

分区(Partition)/ 队列(Queue)

把计算节点分组管理。比如:

  • gpu_queue:只放带 GPU 的节点
  • debug_queue:小任务、短时间,用来调试
  • bigmem_queue:内存特别大的节点

你提交作业时选哪个队列,调度器就把你扔到对应的节点组里。

作业(Job)与任务(Task)

作业是你提交的一个整体任务。任务是一个作业里的子单元——比如你用 MPI 并行跑了 64 个进程,每个进程就是一个 task。

# SLURM 示例:提交一个 4 节点、每节点 8 任务的 MPI 作业
sbatch --nodes=4 --ntasks-per-node=8 my_mpi_job.sh

说白了,你提交的不是命令,而是一个「资源请求书」。调度器看完你的请求,再看看空闲资源,决定什么时候让你跑。

资源分配策略

为什么你的作业老排在我前面?这背后是策略说了算:

  • FIFO——先来后到,简单公平但效率低
  • 公平共享(Fairshare)——每个用户/组按历史用量动态调整优先级
  • 抢占(Preemption)——高优先级作业来了,低优先级的乖乖让位
  • 回填(Backfill)——合理利用碎片资源,小作业插空跑

实际调度器会组合使用这些策略。比如 SLURM 默认用 Fairshare + Backfill,效率最高。

避坑经验:我曾经遇到过一位用户提交了 10000 个单核小作业,结果 Backfill 算法把整个集群的调度队列塞爆了。后来我给他加了一条限制:同一用户最多 500 个 running job。这种配置在 SLURM 里一行就能搞定:

MaxJobs               = 500
MaxSubmitJobs         = 10000

别等到出事了再补——先想清楚你的使用场景。

一张图看清调度系统全貌

下面这张 SVG 图展示了作业从提交到结束的完整生命周期,以及调度器在其中扮演的角色。你可以把它当作整章的「知识地图」。

作业生命周期与调度系统核心角色 用户提交作业 调度队列(排队 + 策略裁决) 资源分配(节点 / GPU) 作业执行(CPU / 内存 / 网络) 性能监控(资源使用 / 状态) 作业完成 / 清理 调度器全程管理:排队策略 → 资源分配 → 执行监控 → 完成后释放 调度器核心

这张图其实道出了调度系统的本质:排队、分配、执行、清理。你提交作业后,调度器会检查你有无权限、资源够不够、优先级高不高,然后决定是立刻跑还是等等再跑。跑完之后,调度器还要帮你释放资源,不给别人留麻烦。

小结

你可能会觉得这些东西很枯燥,但说实话,集群调度的底层逻辑和你在公司门口等出租车没什么两样。有人着急(高优先级),有人想拼车(并行作业),有人行李多(大内存需求),调度器就是那个「最理性的司机」。先把这些概念装进脑子里,后面几章我们上真家伙——写 SLURM 脚本、配队列、追查问题。