【发布时间】:2019-10-24 16:30:50
【问题描述】:
我有一个程序,它接受一个描述一系列初始条件的输入文件并输出一系列最终条件。我还有一个批处理脚本,它通过将输入文件中的初始条件范围分解成更小的块并将它们提供给程序的独立实例来“并行化”程序。只要我只尝试在一个节点上运行批处理脚本,这似乎就可以正常工作,但是如果我请求多个节点,则程序的每个实例在每个节点上都会重复。
这是我正在使用的批处理脚本的一个大大简化的版本,它重复了这个问题:
---my_job_splitter.sh---
#!/bin/env bash
#SBATCH --job-name Test
#SBATCH --output=%x_%j_%t.csv
#SBATCH --error=log.err
#SBATCH --mail-type=END,FAIL
#SBATCH --nodes=4
#Read the command line input
if [ "$#" -ge 4 ]; then
numtasks=${1}
inptrangestart=${2}
inptrangeend=${3}
inptrangenum=${4}
fi
#Calculate the size of the chunks to break the range into
chunksize=$((inptrangenum/numtasks))
#Run a separate instance my_program to process each smaller chunk of the input range
for ((ii=0;ii<numtasks;ii++)); do
stp=`echo "scale=4;($inptrangeend-$inptrangestart)/($inptrangenum-1)" | bc`
a=`echo "$chunksize*$stp*$ii" | bc`
b=`echo "$a+($chunksize-1)*$stp" | bc`
srun my_program.sh $a $b $chunksize &
done
wait
出于说明目的,my_program 只是一个 bash 脚本,它获取输入范围并将其作为 csv 行写入stdout:
---my_program.sh---
#!/bin/env bash
echo "$1,$2,$3"
如果一切都在做我想做的事,如果我运行命令
sbatch my_job_splitter 32 0 1000 4000
输出文件应该是一个包含 32 个条目的 CSV 文件,每个条目的范围为 0:1000 的 1/32,但是我得到一个包含 96 个条目的 CSV 文件,并且每个范围块重复 3 次。我想我明白发生了什么——每次我运行 srun 时,它都会看到我分配了 3 个节点并假设我想要每个节点有 1 个任务,所以它只是复制任务,直到它为每个节点分配了 1 个任务——但我不知道如何解决它,或者这是否是一种愚蠢的做法。
我尝试过的其他事情:
- 在
srun上使用--exclusive标志:这只会导致srun只使用一个节点而忽略其他分配的节点 - 根本不使用
srun:这似乎与使用srun --exclusive的效果相同
【问题讨论】:
-
尝试告诉
srun只使用一个节点 (--nodes 1),尽管我更愿意告诉 SLURM 我需要多少任务并让它分配它认为合适的节点数量。 -
这也导致它只使用分配的 4 个节点中的一个。与使用
--ntasks 1一样,即使我还指定了--cpus-per-task 1。如果我只指定--cpus-per-task 1,那么它将跨所有cpu 和所有节点复制任务。 -
我想显而易见的解决方法是将所有拆分输入写入编号的临时文本文件并使用作业数组,但这就是丑,尤其是当我'我把它分成 80 或 90 个单独的部分。
-
嗯,使用 4 个节点中的一个是预期的结果,对吧?您希望您的
my_program.sh在单个节点中运行,对吗?另一方面,您可以使用作业数组,而无需创建您正在谈论的中间文件:只需即时计算它们的信息。 -
是的,我希望
my_program.sh的任何给定实例仅在单个节点上运行一次,但如果我已将节点 1、2、3 和 4 分配给整个作业,并且批处理脚本在节点 1 上运行,然后 所有 的my_program.sh实例在节点 1 上运行,并且节点 2、3 和 4 不执行任何操作;或节点 2、3 和 4 各自运行重复的实例,其中运行在节点 1 上的实例的重复输入。似乎没有任何方法可以告诉调度程序将my_program.sh实例的 1/4 放在节点上1,其中 1/4 在节点 2 上,等等。