У меня есть программа, которая принимает входной файл, описывающий диапазон начальных условий, и выводит диапазон конечных условий. У меня также есть пакетный сценарий, который «распараллеливает» программу, просто разбивая начальные диапазоны условий во входном файле на более мелкие куски и передавая их в независимые экземпляры программы. Кажется, это работает нормально, пока я пытаюсь запустить пакетный скрипт только на одном узле, но если я запрашиваю более одного узла, каждый экземпляр программы дублируется на каждом узле.
Вот значительно упрощенная версия пакетного скрипта, который я использую, который дублирует проблему:
---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, который принимает диапазон вводаи записывает его в stdout
в виде строки csv:
---my_program.sh---
#!/bin/env bash
echo "$1,$2,$3"
Если бы все делало то, что я хочу, если я запускаю команду sbatch my_job_splitter 32 0 1000 4000
, выходной файл должен быть CSV-файлом с 32 записями, каждыйс 1/32 диапазона 0: 1000, но вместо этого я получаю файл CSV с 96 записями, и каждый фрагмент диапазона дублируется 3 раза. Я думаю, что понимаю, что происходит - каждый раз, когда я запускаю srun, он видит, что я выделил 3 узла, и предполагает, что я хочу 1 задачу на узел, и поэтому он просто дублирует задачу, пока не назначит 1 задачу для каждого узла -но я не знаю, как это исправить или это глупый способ сделать это в первую очередь.
Другие вещи, которые я пробовал:
- Использование
--exclusive
флаг srun
: это просто заставляет srun
использовать только один узел и игнорировать другие выделенные узлы - Не использовать
srun
вообще: похоже, тот же эффект, что и при использовании srun --exclusive