帮派调度

Slurm 支持时间切片的帮派调度,其中两个或更多作业被分配到同一分区的相同资源,并且这些作业交替暂停,以便一次让一个作业专用访问资源,持续配置的时间段。
Slurm 还支持抢占式作业调度,允许在更高的 PriorityTier 分区中的作业或在抢占 QOS 中的作业抢占其他作业。 抢占 与帮派调度相关,因为 SUSPEND 是 PreemptionMode 之一,并且它使用帮派调度器来恢复被暂停的作业。

支持时间切片的工作负载管理器可以通过允许更多作业更早开始运行来提高响应能力和利用率。短时间运行的作业不再需要在长时间运行的作业后面排队。相反,它们可以与长时间运行的作业“并行”运行,这将使它们更快地开始和完成。吞吐量也得到了改善,因为过度分配资源提供了发生“本地回填”的机会(见下例)。

帮派调度逻辑在每个分区独立工作。如果一个新作业被分配到已经分配给现有作业的分区资源,则插件将暂停新作业,直到配置的 SchedulerTimeslice 间隔已过。然后,它将暂停正在运行的作业,并让新作业在 SchedulerTimeslice 间隔内使用资源。这将持续进行,直到其中一个作业终止。

注意: 异构作业被排除在帮派调度操作之外。

配置

与帮派调度相关的几个重要配置参数:

  • SelectType: Slurm 帮派调度器支持由 select/linear 插件分配的节点,支持由 select/cons_tres 插件分配的插槽/核心/CPU 资源。
  • SelectTypeParameters: 由于资源将被作业过度分配(被暂停的作业仍保留在内存中),资源选择插件应配置为跟踪每个作业使用的内存量,以确保不会发生内存页面交换。当选择 select/linear 时,我们建议设置 SelectTypeParameters=CR_Memory。当选择 select/cons_tres 时,我们建议包括内存作为资源(例如 SelectTypeParameters=CR_Core_Memory)。
  • DefMemPerCPU: 由于作业请求可能未明确指定内存要求,我们还建议配置 DefMemPerCPU(每个分配 CPU 的默认内存)或 DefMemPerNode(每个分配节点的默认内存)。在 slurm.conf 中配置 MaxMemPerCPU(每个分配 CPU 的最大内存)或 MaxMemPerNode(每个分配节点的最大内存)也可能是可取的。用户可以在作业提交时使用 --mem--mem-per-cpu 选项来指定其内存要求。请注意,为了进行帮派调度,所有作业必须能够同时适应内存。
  • JobAcctGatherType 和 JobAcctGatherFrequency: 如果您希望强制内存限制,则必须配置该任务/cgroup 以限制每个作业的内存使用,或者使用 JobAcctGatherTypeJobAcctGatherFrequency 参数启用会计。如果启用了会计且作业超过其配置的内存限制,则将取消该作业,以防止其对共享相同资源的其他作业产生不利影响。
  • PreemptMode: 设置 GANG 选项。有关可能指定的其他选项以启用作业 抢占,请参阅 slurm.conf 手册页。为了使用帮派调度,必须在集群级别指定 GANG 选项。
    注意: 帮派调度在每个分区独立执行,因此如果您只希望通过 OverSubscribe 进行时间切片,而不进行任何抢占,则不建议配置具有重叠节点的分区。另一方面,如果您希望使用 PreemptType=preempt/partition_prio 允许来自更高 PriorityTier 分区的作业暂停来自较低 PriorityTier 分区的作业,则需要重叠分区,并且 PreemptMode=SUSPEND,GANG 以使用帮派调度器恢复被暂停的作业。在任何情况下,不会在不同分区的作业之间发生时间切片。
  • SchedulerTimeSlice: 默认时间切片间隔为 30 秒。要更改此持续时间,请在 slurm.conf 中将 SchedulerTimeSlice 设置为所需的间隔(以秒为单位)。例如,要将时间切片间隔设置为一分钟,请设置 SchedulerTimeSlice=60。较短的值可能会增加帮派调度的开销。
  • OverSubscribe: 将分区的 OverSubscribe 设置配置为 FORCE,用于所有将进行时间切片的分区。FORCE 选项支持一个附加参数,控制可以共享计算资源的作业数量(FORCE[:max_share])。默认情况下,max_share 值为 4。要允许来自该分区的最多 6 个作业分配到一个公共资源,请设置 OverSubscribe=FORCE:6。要仅让 2 个作业在相同资源上进行时间切片,请设置 OverSubscribe=FORCE:2

为了在进行上述配置更改后启用帮派调度,如果 Slurm 已在运行,则需要重启 Slurm。对 Slurm 中插件设置的任何更改都需要完全重启守护进程。如果您只是更改分区的 OverSubscribe 设置,则可以使用 scontrol reconfig 更新。

时间切片器设计与操作

启用时,帮派调度器跟踪分配给所有作业的资源。对于每个分区,维护一个“活动位图”,跟踪 Slurm 集群中所有并发运行的作业。每当新作业被分配到分区中的资源时,帮派调度器会将这些新分配的资源与“活动位图”中已经维护的资源进行比较。如果这两组资源不相交,则将新作业添加到“活动位图”中。如果这两组资源重叠,则新作业被暂停。所有作业在帮派调度逻辑中以每个分区的作业队列进行跟踪。

帮派调度器在启动时生成一个单独的 timeslicer thread。该线程在配置的 SchedulerTimeSlice 间隔内休眠。当它醒来时,它检查每个分区是否有被暂停的作业。如果找到被暂停的作业,则 timeslicer thread 将所有正在运行的作业移动到作业队列的末尾。然后,它从等待时间最长的被暂停作业开始,重建该分区的“活动位图”(这将是运行队列中的第一个被暂停作业)。然后将每个后续作业与新的“活动位图”进行比较,如果该作业可以与其他“活动”作业并发运行,则将该作业添加。一旦完成,timeslicer thread 将暂停不再是“活动位图”一部分的任何当前运行作业,并恢复新进入“活动位图”的作业。

timeslicer thread 轮换作业的算法旨在防止作业饿死(无限期保持在暂停状态),并在分配运行时间时尽可能公平,同时保持所有资源尽可能繁忙。

帮派调度器通过支持 scontrol suspendscontrol resume 的相同内部函数来暂停作业。观察时间切片器操作的好方法是在终端窗口中运行 squeue -i<time>,其中 time 设置为 SchedulerTimeSlice

一个简单的例子

以下示例配置为 select/linearOverSubscribe=FORCE。该示例发生在一个由 5 个节点组成的小集群上:

[user@n16 load]$ sinfo
PARTITION AVAIL  TIMELIMIT NODES  STATE NODELIST
active*      up   infinite     5   idle n[12-16]

以下是调度器设置(输出摘录):

[user@n16 load]$ scontrol show config
...
PreemptMode             = GANG
...
SchedulerTimeSlice      = 30
SchedulerType           = sched/builtin
...

myload 脚本启动一个简单的负载生成应用程序,运行指定的秒数。提交 myload 在所有节点上运行:

[user@n16 load]$ sbatch -N5 ./myload 300
sbatch: 提交批处理作业 3

[user@n16 load]$ squeue
JOBID PARTITION    NAME  USER ST  TIME NODES NODELIST
    3    active  myload  user     0:05     5 n[12-16]

再次提交并观察帮派调度器如何暂停它:

[user@n16 load]$ sbatch -N5 ./myload 300
sbatch: 提交批处理作业 4

[user@n16 load]$ squeue
JOBID PARTITION    NAME  USER ST  TIME NODES NODELIST
    3    active  myload  user  R  0:13     5 n[12-16]
    4    active  myload  user  S  0:00     5 n[12-16]

30 秒后,帮派调度器交换作业,现在作业 4 是活动的:

[user@n16 load]$ squeue
JOBID PARTITION    NAME  USER ST  TIME NODES NODELIST
    4    active  myload  user  R  0:08     5 n[12-16]
    3    active  myload  user  S  0:41     5 n[12-16]

[user@n16 load]$ squeue
JOBID PARTITION    NAME  USER ST  TIME NODES NODELIST
    4    active  myload  user  R  0:21     5 n[12-16]
    3    active  myload  user  S  0:41     5 n[12-16]

再过 30 秒,帮派调度器再次启动作业 3:

[user@n16 load]$ squeue
JOBID PARTITION    NAME  USER ST  TIME NODES NODELIST
    3    active  myload  user  R  0:50     5 n[12-16]
    4    active  myload  user  S  0:30     5 n[12-16]

时间切片的一个可能副作用: 请注意,立即被暂停的作业可能会导致其 srun 命令产生以下输出:

[user@n16 load]$ cat slurm-4.out
srun: 作业步骤创建暂时禁用,重试中
srun: 作业步骤创建仍然禁用,重试中
srun: 作业步骤创建仍然禁用,重试中
srun: 作业步骤创建仍然禁用,重试中
srun: 作业步骤创建

这是因为 srun 正在尝试在一个已被暂停的分配中启动作业步骤。srun 进程将继续在重试循环中启动作业步骤,直到分配已恢复并且作业步骤可以启动。

当启用帮派调度器时,用户作业中的这种输出应视为良性。

更多示例

以下示例展示了时间切片算法如何保持资源繁忙。作业 10 持续运行,而作业 9 和 11 被时间切片:

[user@n16 load]$ sbatch -N3 ./myload 300
sbatch: 提交批处理作业 9

[user@n16 load]$ sbatch -N2 ./myload 300
sbatch: 提交批处理作业 10

[user@n16 load]$ sbatch -N3 ./myload 300
sbatch: 提交批处理作业 11

[user@n16 load]$ squeue
JOBID PARTITION    NAME  USER ST  TIME NODES NODELIST
    9    active  myload  user  R  0:11     3 n[12-14]
   10    active  myload  user  R  0:08     2 n[15-16]
   11    active  myload  user  S  0:00     3 n[12-14]

[user@n16 load]$ squeue
JOBID PARTITION    NAME  USER ST  TIME NODES NODELIST
   10    active  myload  user  R  0:50     2 n[15-16]
   11    active  myload  user  R  0:12     3 n[12-14]
    9    active  myload  user  S  0:41     3 n[12-14]

[user@n16 load]$ squeue
JOBID PARTITION    NAME  USER ST  TIME NODES NODELIST
   10    active  myload  user  R  1:04     2 n[15-16]
   11    active  myload  user  R  0:26     3 n[12-14]
    9    active  myload  user  S  0:41     3 n[12-14]

[user@n16 load]$ squeue
JOBID PARTITION    NAME  USER ST  TIME NODES NODELIST
    9    active  myload  user  R  0:46     3 n[12-14]
   10    active  myload  user  R  1:13     2 n[15-16]
   11    active  myload  user  S  0:30     3 n[12-14]

下一个示例显示“本地回填”:

[user@n16 load]$ sbatch -N3 ./myload 300
sbatch: 提交批处理作业 12

[user@n16 load]$ sbatch -N5 ./myload 300
sbatch: 提交批处理作业 13

[user@n16 load]$ sbatch -N2 ./myload 300
sbatch: 提交批处理作业 14

[user@n16 load]$ squeue
JOBID PARTITION    NAME  USER ST  TIME NODES NODELIST
   12    active  myload  user  R  0:14     3 n[12-14]
   14    active  myload  user  R  0:06     2 n[15-16]
   13    active  myload  user  S  0:00     5 n[12-16]

在没有时间切片且未启用回填调度器的情况下,作业 14 必须等待作业 13 完成。

这被称为“本地”回填,因为回填仅发生在队列中足够接近的作业之间,以便调度器将其分配为过度分配资源的一部分。请记住,可以过度分配资源的作业数量由 OverSubscribe=FORCE:max_share 值控制,因此该值有效地控制了“本地回填”的范围。

正常的回填算法检查 所有 等待队列中的作业。

可消耗资源示例

以下两个示例说明了在启用可消耗资源选择(select/cons_tres)时 CR_CPUCR_Core 之间的主要区别。

当配置 CR_CPU(或 CR_CPU_Memory)时,选择器将 CPU 视为简单的 可互换 计算资源 除非 启用了任务亲和性。然而,当启用任务亲和性时,CR_CPUCR_Core(或 CR_Core_Memory)时,选择器将 CPU 视为单独的资源,专门 分配给作业。当启用时间切片时,这一细微差别尤为明显。

在这两个示例中提交了 6 个作业。每个作业请求每个节点 2 个 CPU,所有节点都包含两个四核处理器。时间切片器最初将让前 4 个作业运行并暂停最后 2 个作业。这些作业的时间切片方式取决于配置的 SelectTypeParameters

在第一个示例中配置了 CR_Core_Memory。请注意,作业 46 和 47 从未被暂停。这是因为它们没有与任何其他作业共享其核心。作业 48 和 49 被分配到与作业 44 和 45 相同的核心。时间切片器识别到这一点并仅对这些作业进行时间切片:

[user@n16 load]$ sinfo
PARTITION AVAIL  TIMELIMIT NODES  STATE NODELIST
active*      up   infinite     5   idle n[12-16]

[user@n16 load]$ scontrol show config | grep Select
SelectType              = select/cons_tres
SelectTypeParameters    = CR_CORE_MEMORY

[user@n16 load]$ sinfo -o "%20N %5D %5c %5z"
NODELIST             NODES CPUS  S:C:T
n[12-16]             5     8     2:4:1

[user@n16 load]$ sbatch -n10 -N5 ./myload 300
sbatch: 提交批处理作业 44

[user@n16 load]$ sbatch -n10 -N5 ./myload 300
sbatch: 提交批处理作业 45

[user@n16 load]$ sbatch -n10 -N5 ./myload 300
sbatch: 提交批处理作业 46

[user@n16 load]$ sbatch -n10 -N5 ./myload 300
sbatch: 提交批处理作业 47

[user@n16 load]$ sbatch -n10 -N5 ./myload 300
sbatch: 提交批处理作业 48

[user@n16 load]$ sbatch -n10 -N5 ./myload 300
sbatch: 提交批处理作业 49

[user@n16 load]$ squeue
JOBID PARTITION    NAME  USER ST  TIME NODES NODELIST
   44    active  myload  user  R  0:09     5 n[12-16]
   45    active  myload  user  R  0:08     5 n[12-16]
   46    active  myload  user  R  0:08     5 n[12-16]
   47    active  myload  user  R  0:07     5 n[12-16]
   48    active  myload  user  S  0:00     5 n[12-16]
   49    active  myload  user  S  0:00     5 n[12-16]

[user@n16 load]$ squeue
JOBID PARTITION    NAME  USER ST  TIME NODES NODELIST
   46    active  myload  user  R  0:49     5 n[12-16]
   47    active  myload  user  R  0:48     5 n[12-16]
   48    active  myload  user  R  0:06     5 n[12-16]
   49    active  myload  user  R  0:06     5 n[12-16]
   44    active  myload  user  S  0:44     5 n[12-16]
   45    active  myload  user  S  0:43     5 n[12-16]

[user@n16 load]$ squeue
JOBID PARTITION    NAME  USER ST  TIME NODES NODELIST
   44    active  myload  user  R  1:23     5 n[12-16]
   45    active  myload  user  R  1:22     5 n[12-16]
   46    active  myload  user  R  2:22     5 n[12-16]
   47    active  myload  user  R  2:21     5 n[12-16]
   48    active  myload  user  S  1:00     5 n[12-16]
   49    active  myload  user  S  1:00     5 n[12-16]

请注意最后一个 squeue 命令输出中所有 6 个作业的运行时间。作业 46 和 47 一直在运行,而作业 44 和 45 正在与作业 48 和 49 分配运行时间。

下一个示例配置了 CR_CPU_Memory,并提交了相同的 6 个作业。在这里,选择器和时间切片器将 CPU 视为可计数的资源,这导致所有 6 个作业共享 CPU 的时间:

[user@n16 load]$ sinfo
PARTITION AVAIL  TIMELIMIT NODES  STATE NODELIST
active*      up   infinite     5   idle n[12-16]

[user@n16 load]$ scontrol show config | grep Select
SelectType              = select/cons_tres
SelectTypeParameters    = CR_CPU_MEMORY

[user@n16 load]$ sinfo -o "%20N %5D %5c %5z"
NODELIST             NODES CPUS  S:C:T
n[12-16]             5     8     2:4:1

[user@n16 load]$ sbatch -n10 -N5 ./myload 300
sbatch: 提交批处理作业 51

[user@n16 load]$ sbatch -n10 -N5 ./myload 300
sbatch: 提交批处理作业 52

[user@n16 load]$ sbatch -n10 -N5 ./myload 300
sbatch: 提交批处理作业 53

[user@n16 load]$ sbatch -n10 -N5 ./myload 300
sbatch: 提交批处理作业 54

[user@n16 load]$ sbatch -n10 -N5 ./myload 300
sbatch: 提交批处理作业 55

[user@n16 load]$ sbatch -n10 -N5 ./myload 300
sbatch: 提交批处理作业 56

[user@n16 load]$ squeue
JOBID PARTITION    NAME  USER ST  TIME NODES NODELIST
   51    active  myload  user  R  0:11     5 n[12-16]
   52    active  myload  user  R  0:11     5 n[12-16]
   53    active  myload  user  R  0:10     5 n[12-16]
   54    active  myload  user  R  0:09     5 n[12-16]
   55    active  myload  user  S  0:00     5 n[12-16]
   56    active  myload  user  S  0:00     5 n[12-16]

[user@n16 load]$ squeue
JOBID PARTITION    NAME  USER ST  TIME NODES NODELIST
   51    active  myload  user  R  1:09     5 n[12-16]
   52    active  myload  user  R  1:09     5 n[12-16]
   55    active  myload  user  R  0:23     5 n[12-16]
   56    active  myload  user  R  0:23     5 n[12-16]
   53    active  myload  user  S  0:45     5 n[12-16]
   54    active  myload  user  S  0:44     5 n[12-16]

[user@n16 load]$ squeue
JOBID PARTITION    NAME  USER ST  TIME NODES NODELIST
   53    active  myload  user  R  0:55     5 n[12-16]
   54    active  myload  user  R  0:54     5 n[12-16]
   55    active  myload  user  R  0:40     5 n[12-16]
   56    active  myload  user  R  0:40     5 n[12-16]
   51    active  myload  user  S  1:16     5 n[12-16]
   52    active  myload  user  S  1:16     5 n[12-16]

[user@n16 load]$ squeue
JOBID PARTITION    NAME  USER ST  TIME NODES NODELIST
   51    active  myload  user  R  3:18     5 n[12-16]
   52    active  myload  user  R  3:18     5 n[12-16]
   53    active  myload  user  R  3:17     5 n[12-16]
   54    active  myload  user  R  3:16     5 n[12-16]
   55    active  myload  user  S  3:00     5 n[12-16]
   56    active  myload  user  S  3:00     5 n[12-16]

请注意,所有 6 个作业的运行时间大致相等。作业 51-54 首先运行,因此它们稍微领先,但到目前为止,所有作业都至少运行了 3 分钟。

在核心级别,这意味着 Slurm 依赖于 Linux 内核在核心之间移动作业以最大化性能。这与配置 CR_Core_Memory 时的情况不同,当时作业在作业持续期间实际上会“固定”在其特定核心上。请注意,CR_Core_Memory 支持 CPU 绑定,而 CR_CPU_Memory 不支持。

请注意,手动暂停作业(即“scontrol suspend ...”)会释放其 CPU 以分配给其他作业。恢复先前暂停的作业可能会导致多个作业被分配到相同的 CPU,这可能会触发作业的帮派调度。在许多情况下,使用 scancel 命令发送 SIGSTOP 和 SIGCONT 信号将停止作业而不释放其 CPU 以分配给其他作业,这将是更可取的机制。

最后修改于 2024 年 1 月 29 日