作业数组支持
概述
作业数组提供了一种快速简便地提交和管理相似作业集合的机制;具有数百万任务的作业数组可以在毫秒内提交(受配置大小限制)。 所有作业必须具有相同的初始选项(例如大小、时间限制等),但是可以在作业开始执行后使用 scontrol 命令更改这些选项,指定数组的 JobID 或单个 ArrayJobID。
$ scontrol update job=101 ... $ scontrol update job=101_1 ...
作业数组仅支持批处理作业,数组索引值使用 sbatch 命令的 --array 或 -a 选项指定。选项参数可以是特定的数组索引值、索引值范围以及可选的步长,如下例所示。 注意,最小索引值为零,最大值为 Slurm 配置参数(MaxArraySize 减一)。 属于作业数组的作业将设置环境变量 SLURM_ARRAY_TASK_ID 为其数组索引值。
# 提交一个索引值在 0 到 31 之间的作业数组 $ sbatch --array=0-31 -N1 tmp # 提交一个索引值为 1, 3, 5 和 7 的作业数组 $ sbatch --array=1,3,5,7 -N1 tmp # 提交一个索引值在 1 到 7 之间的作业数组 # 步长为 2(即 1, 3, 5 和 7) $ sbatch --array=1-7:2 -N1 tmp
可以使用 "%" 分隔符指定作业数组中同时运行任务的最大数量。 例如 "--array=0-15%4" 将限制此作业数组中同时运行的任务数量为 4。
作业ID和环境变量
作业数组将设置额外的环境变量。
SLURM_ARRAY_JOB_ID 将被设置为数组的第一个作业 ID。
SLURM_ARRAY_TASK_ID 将被设置为作业数组索引值。
SLURM_ARRAY_TASK_COUNT 将被设置为作业数组中的任务数量。
SLURM_ARRAY_TASK_MAX 将被设置为最高的作业数组索引值。
SLURM_ARRAY_TASK_MIN 将被设置为最低的作业数组索引值。
在正常情况下,数组作业的第一个任务将作为数组其余部分的占位符,导致它最后运行。
因此,具有最低 SLURM_JOB_ID 的任务将具有最高的 SLURM_ARRAY_TASK_ID。
例如,这种作业提交:
sbatch --array=1-3 -N1 tmp
将生成一个包含三个作业的作业数组。如果 sbatch 命令响应:
Submitted batch job 36
那么环境变量将设置如下:
SLURM_JOB_ID=36 SLURM_ARRAY_JOB_ID=36 SLURM_ARRAY_TASK_ID=3 SLURM_ARRAY_TASK_COUNT=3 SLURM_ARRAY_TASK_MAX=3 SLURM_ARRAY_TASK_MIN=1 SLURM_JOB_ID=37 SLURM_ARRAY_JOB_ID=36 SLURM_ARRAY_TASK_ID=1 SLURM_ARRAY_TASK_COUNT=3 SLURM_ARRAY_TASK_MAX=3 SLURM_ARRAY_TASK_MIN=1 SLURM_JOB_ID=38 SLURM_ARRAY_JOB_ID=36 SLURM_ARRAY_TASK_ID=2 SLURM_ARRAY_TASK_COUNT=3 SLURM_ARRAY_TASK_MAX=3 SLURM_ARRAY_TASK_MIN=1
如上所示的任务顺序不保证。例如,当任务被重新排队时,可能会有个别任务被创建的顺序不一致。如果任务在开始前被更新/修改,具有最低 JOB_ID 的任务可能没有最高的 TASK_ID。其他边缘情况可能导致类似的行为。
所有 Slurm 命令和 API 都识别 SLURM_JOB_ID 值。 大多数命令还识别 SLURM_ARRAY_JOB_ID 加上 SLURM_ARRAY_TASK_ID 值,以下划线分隔,作为识别作业数组元素的方式。 使用上述示例,“37”或“36_1”将是识别作业 36 的第二个数组元素的等效方式。 一组 API 已被开发,用于在单个函数调用中操作整个作业数组或选择作业数组的任务。 函数响应由一个数组组成,标识作业 ID 的各个任务的各种错误代码。 例如,job_resume2() 函数可能返回一个错误代码数组,指示任务 1 和 2 已经完成;任务 3 到 5 成功恢复,任务 6 到 99 尚未开始。
文件名
有两个额外的选项可用于指定作业的 stdin、stdout 和 stderr 文件名:
%A 将被替换为 SLURM_ARRAY_JOB_ID 的值(如上所定义),
%a 将被替换为 SLURM_ARRAY_TASK_ID 的值(如上所定义)。
作业数组的默认输出文件格式为 "slurm-%A_%a.out"。
显式使用格式化的示例如下:
sbatch -o slurm-%A_%a.out --array=1-3 -N1 tmp
这将生成类似于 "slurm-36_1.out"、"slurm-36_2.out" 和 "slurm-36_3.out" 的输出文件名。
如果这些文件名选项在不属于作业数组的情况下使用,则 "%A" 将被替换为当前作业 ID,"%a" 将被替换为 4,294,967,294(相当于 0xfffffffe 或 NO_VAL)。
Scancel 命令使用
如果作业数组的作业 ID 被指定为 scancel 命令的输入,则该作业数组的所有元素将被取消。 或者,可以使用正则表达式指定数组 ID 以取消作业。
# 取消作业数组 20 中的数组 ID 1 到 3 $ scancel 20_[1-3] # 取消作业数组 20 中的数组 ID 4 和 5 $ scancel 20_4 20_5 # 取消作业数组 20 的所有元素 $ scancel 20 # 取消当前作业或作业数组元素(如果是作业数组) if [[-z $SLURM_ARRAY_JOB_ID]]; then scancel $SLURM_JOB_ID else scancel ${SLURM_ARRAY_JOB_ID}_${SLURM_ARRAY_TASK_ID} fi
Squeue 命令使用
当作业数组提交到 Slurm 时,只会创建一个作业记录。 只有当作业数组中的任务状态发生变化时,才会创建额外的作业记录,通常是在任务分配资源或其状态使用 scontrol 命令修改时。 默认情况下,squeue 命令将在一行上报告与单个作业记录关联的所有任务,并使用正则表达式指示“array_task_id”值,如下所示。
$ squeue JOBID PARTITION NAME USER ST TIME NODES NODELIST(REASON) 1080_[5-1024] debug tmp mac PD 0:00 1 (Resources) 1080_1 debug tmp mac R 0:17 1 tux0 1080_2 debug tmp mac R 0:16 1 tux1 1080_3 debug tmp mac R 0:03 1 tux2 1080_4 debug tmp mac R 0:03 1 tux3
还为 squeue 命令添加了一个 "--array" 或 "-r" 选项,以每行打印一个作业数组元素,如下所示。 环境变量 "SQUEUE_ARRAY" 等效于在 squeue 命令行中包含 "--array" 选项。
$ squeue -r JOBID PARTITION NAME USER ST TIME NODES NODELIST(REASON) 1082_3 debug tmp mac PD 0:00 1 (Resources) 1082_4 debug tmp mac PD 0:00 1 (Priority) 1080 debug tmp mac R 0:17 1 tux0 1081 debug tmp mac R 0:16 1 tux1 1082_1 debug tmp mac R 0:03 1 tux2 1082_2 debug tmp mac R 0:03 1 tux3
squeue --step/-s 和 --job/-j 选项可以接受相同格式的作业或步骤规范。
$ squeue -j 1234_2,1234_3 ... $ squeue -s 1234_2.0,1234_3.0 ...
squeue 中增加了两个额外的作业输出格式字段选项:
%F 打印 array_job_id 值
%K 打印 array_task_id 值
(所有明显的字母都已分配给其他作业字段)。
Scontrol 命令使用
使用 scontrol show job 选项显示与作业数组支持相关的两个新字段。 JobID 是作业的唯一标识符。 ArrayJobID 是作业数组第一个元素的 JobID。 ArrayTaskID 是此特定条目的数组索引,可能是单个数字或标识此作业记录所代表条目的表达式(例如“5-1024”)。 如果作业不属于作业数组,则不会显示这两个字段。 scontrol show job 或 scontrol show step 命令中指定的可选作业 ID 可以通过指定 ArrayJobId 和 ArrayTaskId 并在它们之间使用下划线来识别作业数组元素(例如 <ArrayJobID>_<ArrayTaskId>)。
如果指定的作业 ID 是 ArrayJobID,则 scontrol 命令将对作业数组的所有元素进行操作。 可以使用 ArrayJobID_ArrayTaskID 修改单个作业数组任务,如下所示。
$ sbatch --array=1-4 -J array ./sleepme 86400 Submitted batch job 21845 $ squeue JOBID PARTITION NAME USER ST TIME NODES NODELIST 21845_1 canopo array david R 0:13 1 dario 21845_2 canopo array david R 0:13 1 dario 21845_3 canopo array david R 0:13 1 dario 21845_4 canopo array david R 0:13 1 dario $ scontrol update JobID=21845_2 name=arturo $ squeue JOBID PARTITION NAME USER ST TIME NODES NODELIST 21845_1 canopo array david R 17:03 1 dario 21845_2 canopo arturo david R 17:03 1 dario 21845_3 canopo array david R 17:03 1 dario 21845_4 canopo array david R 17:03 1 dario
scontrol hold, holdu, release, requeue, requeuehold, suspend 和 resume 命令也可以对作业数组的所有元素或单个元素进行操作,如下所示。
$ scontrol suspend 21845 $ squeue JOBID PARTITION NAME USER ST TIME NODES NODELIST 21845_1 canopo array david S 25:12 1 dario 21845_2 canopo arturo david S 25:12 1 dario 21845_3 canopo array david S 25:12 1 dario 21845_4 canopo array david S 25:12 1 dario $ scontrol resume 21845 $ squeue JOBID PARTITION NAME USER ST TIME NODES NODELIST 21845_1 canopo array david R 25:14 1 dario 21845_2 canopo arturo david R 25:14 1 dario 21845_3 canopo array david R 25:14 1 dario 21845_4 canopo array david R 25:14 1 dario scontrol suspend 21845_3 $ squeue JOBID PARTITION NAME USER ST TIME NODES NODELIST 21845_1 canopo array david R 25:14 1 dario 21845_2 canopo arturo david R 25:14 1 dario 21845_3 canopo array david S 25:14 1 dario 21845_4 canopo array david R 25:14 1 dario scontrol resume 21845_3 $ squeue JOBID PARTITION NAME USER ST TIME NODES NODELIST 21845_1 canopo array david R 25:14 1 dario 21845_2 canopo arturo david R 25:14 1 dario 21845_3 canopo array david R 25:14 1 dario 21845_4 canopo array david R 25:14 1 dario
作业依赖
依赖于整个作业数组的作业应指定其依赖于 ArrayJobID。 由于每个数组元素可以具有不同的退出代码,afterok 和 afternotok 子句的解释将基于作业数组中任何任务的最高退出代码。
当作业依赖指定作业数组的作业 ID 时:
after 子句在作业数组中的所有任务开始后满足。
afterany 子句在作业数组中的所有任务完成后满足。
aftercorr 子句在指定作业中的相应任务 ID 成功完成后满足(以退出代码零完成)。
afterok 子句在作业数组中的所有任务成功完成后满足。
afternotok 子句在作业数组中的所有任务完成且至少有一个任务未成功完成后满足。
使用示例如下:
# 等待特定作业数组元素 sbatch --depend=after:123_4 my.job sbatch --depend=afterok:123_4:123_8 my.job2 # 等待整个作业数组完成 sbatch --depend=afterany:123 my.job # 等待相应的作业数组元素 sbatch --depend=aftercorr:123 my.job # 等待整个作业数组成功完成 sbatch --depend=afterok:123 my.job # 等待整个作业数组完成且至少有一个任务失败 sbatch --depend=afternotok:123 my.job
其他命令使用
以下 Slurm 命令当前不识别作业数组,其使用需要使用 Slurm 作业 ID,这对每个数组元素都是唯一的:sbcast、sprio、sreport、sshare 和 sstat。 sacct、sattach 和 strigger 命令已被修改以允许指定作业 ID 或作业数组元素。 sview 命令已被修改以允许显示作业的 ArrayJobId 和 ArrayTaskId 字段。如果作业不属于作业数组,这两个字段将显示为“N/A”。
系统管理
已添加一个新的配置参数以控制最大作业数组大小:MaxArraySize。用户可以指定的最小索引为零,最大索引为 MaxArraySize 减一。 MaxArraySize 的默认值为 1001。 Slurm 支持的最大 MaxArraySize 为 4000001。 请注意 MaxArraySize 的值,因为作业数组为用户提供了一种快速提交大量作业的简便方法。
sched/backfill 插件已被修改以提高作业数组的性能。一旦发现作业数组的一个元素不可运行或影响待定作业的调度,作业数组的其余元素将被快速跳过。
当作业数组提交时,Slurm 会创建一个作业记录。 只有在需要时才会创建额外的作业记录,通常是在作业数组的任务启动时,这提供了一种非常可扩展的机制来管理大量作业。 作业数组的每个任务将共享相同的 ArrayJobId,但将拥有自己唯一的 ArrayTaskId。除了 ArrayJobId,每个作业还将拥有一个唯一的 JobId,该 ID 在任务启动时分配。
最后修改于 2024 年 1 月 1 日