Slurm阵列作业,每个节点最多有一个并发作业



问题

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

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

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可以在节点上运行,这会导致等待时间很长,利用率很低。

有什么想法/建议吗?有没有办法为每个作业保留一个特定的端口?

我可以想出两种方法来实现这一点,一种是有一些管理帮助,另一种是没有

  1. 如果你很好地询问你的Slurm管理员,他可能会向节点添加一个"假"gres。这允许您为您的工作申请此gres。如果每个节点只有一个这样的gres,那么无论需要多少其他资源,每个节点都应该限制为一个作业
  2. 您可以请求一个有很多节点的大型作业,但每个节点一个任务,每个节点四个核心,而不是使用阵列。在该作业中,您使用srun启动任务,因为每个节点都有一个任务,所以它们应该沿着节点分布。您可能不想等待128个节点上的四个核心同时空闲,所以将您的工作负载分成块,并将它们作为依赖项提交(查看singleton选项(

详述第二个选项:

#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,这可能是一个选项。

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

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

如果端口不可用,请使用scontrol requeueSLURM_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=$SSLRM_job_ID ExcNodeList=$(hostname-s(`。理想情况下,代码应该更聪明一点,从作业中检索当前排除的节点列表并附加当前节点。

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

最新更新