问题描述
我的问题与此问题类似
长话短说,我想在尽可能多的节点上使用所有可用的CPU内核。
区别在于,我的工作由N个独立任务组成,而不是MPI程序的单个任务,每个任务1个核心。 N可能大于可用核心的总数,在这种情况下,某些任务将只需要等待。
例如,假设我有32个核心的集群。并说我想运行相同的程序(worker_script.sh
),运行100次,每次输入不同。对worker_script.sh
的每次调用都是一个任务。我希望前32个任务可以运行,而其余68个任务可以排队。当内核释放时,以后的任务将运行。最终,当所有任务都完成运行后,我的工作就被视为完成。
正确的做法是什么?我执行了以下脚本,并使用sbatch
对其进行了调用。但是它只是将所有内容都运行在同一内核上。因此,它最终将永远消失。
#!/bin/bash
ctr=0
while [[ $ctr -lt 100 ]]; do
srun worker_script.sh $ctr &
((ctr++))
done
wait
或者,我可以直接调用上面的脚本。这似乎可以解决问题。与之一样,它接管了所有32个核心,同时将其他所有事物排入了队列。释放内核后,它们将被分配给对worker_script.sh
的其余调用。最终,所有100个工作都按预期完成了。
区别在于它不是100个任务的1个作业,而是每个1个任务的100个作业。
是否有不能执行100个独立任务的原因?我从根本上是错误的吗?我应该做100个工作而不是100个任务吗?
解决方法
如果您通过sbatch
提交该脚本,它将为任务分配一个任务。在作业内部,srun
命令仅限于作业的资源。因此,当您通过sbatch
提交计算时,计算将按顺序运行。
如果仅运行脚本而没有sbatch
,则对srun
的调用每次都会创建一个新作业(正如您已经注意到的那样),因此它不仅限于一个任务。
是否有不能执行100个独立任务的原因?我从根本上是错误的吗?我应该做100个工作而不是100个任务吗?
最后,您偏爱个人喜好。您可以完成一项任务,其中包含100个任务:
#!/bin/bash
#SBATCH -n 32
ctr=0
while [[ $ctr -lt 100 ]]; do
srun -n 1 worker_script.sh $ctr &
((ctr++))
done
wait
这将分配32个任务,每个srun调用将消耗1个任务,其余应为。缺点:您将需要等待32个任务一次空闲。这意味着您可能会在队列中等待更长的时间。
(我认为)更好的方法是使用job array:
#!/bin/bash
#SBATCH -a 0-99%32
worker_script.sh $SLURM_ARRAY_TASK_ID
这将创建一个包含100个作业的作业阵列。其中32个可以同时运行。如果不需要/想要后者,则只需从#SBATCH
参数中删除%32部分。
为什么这样更好?如果您的任务是完全独立的,则没有必要将它们全部集中在一份工作中。这样一来,只要有可用的插槽,任务就可以立即运行。这样可以将排队时间减至最少。
此外,使用作业数组很优雅,并且减轻了调度程序的负担。与在for循环中提交的大量相同工作相比,您的管理员可能更喜欢拥有大量工作。
,看看sbatch
而不是srun
,请参阅here中的文档。
#!/bin/bash
ctr=0
while [[ $ctr -lt 100 ]]; do
sbatch worker_script.sh $ctr -n 1 & ((ctr++))
done
srun
是所谓的“交互/阻止”,但是sbatch将作业提交到集群并将stdout / stderr输出到文件。