【问题标题】:Slurm array job with at most one concurrent job per nodeSlurm 数组作业,每个节点最多有一个并发作业
【发布时间】:2021-09-04 11:08:41
【问题描述】:

问题

我有数百个文件,对于每个文件,我想运行一个具有固定数量核心的作业(比如说-c4),这样任何时候都不会有超过一个这些作业在任何节点上运行。

(如果您感兴趣,原因是:复杂的作业设置超出了我的控制。每个作业都会在硬编码端口上启动一堆服务器。如果在一个节点上同时运行,这些会发生冲突:-/(是的,不要告诉我,我知道。))

MVCE

我已经尝试过-N1-n1--ntasks-per-node=1 和内部srun--exclusive 的各种组合,但遗憾的是没有成功:

sbatch -N1 -n1 -c4 --ntasks-per-node=1 --array=1-128 --wrap \
    'echo "$(hostname) $(date) $(sleep 15) $(date)"'

sbatch -N1 -n1 -c4 --ntasks-per-node=1 --array=1-128 --wrap \
    'srun --exclusive -n1 -c4 --ntasks-per-node=1 -- \
         bash -c '\''echo "$(hostname) $(date) $(sleep 15) $(date)"'\'

但是,如果您查看输出 (cat slurm-*.out),您将在所有情况下快速发现重叠运行:-/

问题

有没有办法限制一个数组作业在任何节点上永远不会同时运行超过 1 个作业?

我们的集群非常异构。每个节点中的 CPU(范围从 32 到 256),所以简单的解决方法(例如要求足够高的-c 以便没有 2 可以在节点上运行)会导致非常长的等待时间和低利用率。

任何想法/指针? 有没有办法为每个作业保留某个端口?

【问题讨论】:

    标签: cluster-computing slurm


    【解决方案1】:

    我可以想到两种方法来实现这一点,一种有一些管理员帮助,另一种没有。:

    1. 如果您很好地询问您的 Slurm 管理员,他可能会向节点添加一个“假”gres。这允许您为您的工作请求此 gres。如果每个节点只有一个 gres,则应将每个节点限制为一个作业,无论您需要多少其他资源。
    2. 您可以请求一个包含大量节点的大型作业,但每个节点一个任务,每个节点四个核心,而不是使用数组。在该作业中,您使用 srun 启动任务,并且由于每个节点都有一个任务,它们应该沿着节点分布。您可能不想一次等待 128 个节点上的四个内核空闲,因此将您的工作负载分成块并将它们提交为 dependencies(查看单例选项)。

    第二个选项的详细说明:

    #SBATCH -N16
    #SBATCH --ntasks-per-node=1
    #SBATCH --job-name=something
    #SBATCH --dependency=singleton
    
    for i in `seq 1 $SLURM_JOB_NUM_NODES`; do
      srun -N1 -n1 <your_program> &
    done
    wait
    

    您可以连续提交 100 个这样的文件,它们将依次运行大小为 16 的块。这不是很有效,但是一次等待 100 个节点有一个空闲任务(所以没有分块),可能需要更长的时间。我当然更喜欢第一个选项,但如果您的管理员不想添加一些 gres,这可能是一个选项。

    【讨论】:

    • 嗯,感谢 gres 的想法,肯定会问我们是否可以向所有节点添加一个假的 gres“单例”......我不确定我是否完全理解第二种选择,也许您可以详细说明一下:内部srun 命令是否都与srun ... &amp; 一起运行(所以bg?)?他们还需要-d singleton吗?如果我把它分块,我是否能够在整个系统中最多使用一个活动块,然后如果有更多的空闲/没有作业溢出到其他块,节点的使用率就会很低?
    • 我详细阐述了第二个选项。这并不理想,但至少您不需要等待管理员使用它。
    【解决方案2】:

    最有效的方法是@Marcus Boden 建议的gres 方法。

    但如果管理员无法帮助您,您可以在提交脚本的开头添加一小段代码,以检查所需端口是否可用(例如 @987654322 @ 命令)。

    如果端口不可用,请使用scontrol requeue SLURM_JOB_ID. Before requeueing, in order to prevent the job from hitting the same, unavailable, node, you can edit the job to exclude that node: scontrol update jobid=$SLURM_JOB_ID ExcNodeList=$(hostname -s)` 重新排队作业。理想情况下,代码应该更聪明一点,从作业中检索当前排除的节点列表并附加当前节点。

    另一种选择是使用scontrol update jobid=$SLURM_JOB_ID StartTime=.... 修改作业,并将开始时间设置为当前时间加上作业的典型挂起时间,这样当作业再次符合条件时,当前正在运行的作业节点将完成。但当然,不能保证节点不会同时被分配给另一个作业。

    【讨论】:

    • 有趣的想法......只是为了澄清,这意味着从工作内部调用scontrol requeue ... ; exit 1?似乎有点像greenlets,其中节点上的第二个作业刚刚产生......我可以看到一个竞争条件弹出,但这可以通过NAS上的每个节点的锁定文件和短暂的等待来管理。锁定文件也可用于在重新安排时排除主机......但是,如果您想在所有节点都被使用的情况下避免锁定并且可能需要独立更新来自头节点以防作业提前终止,那么也可能会有点棘手。
    • 是的,除了不需要exit 1requeue 将停止工作。需要说明的是,这是一个肮脏的解决方法,最好的选择当然是在软件中将端口设置为参数,第二好的选择是gres,只有当您无法获得任何其他选项时.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-31
    • 2018-10-07
    • 2020-01-22
    相关资源
    最近更新 更多