Могу ли я использовать mpiexec для запуска одного и того же исполняемого файла с разными аргументами командной строки для исполняемого файла каждый раз?

Я новичок в распределенной операционной системе. И мне нужно обучить несколько моделей машинного обучения с помощью суперкомпьютеров. Мне нужно запустить один и тот же сценарий обучения несколько раз, и для каждого запуска передать сценарий с другим аргументом командной строки. Могу ли я добиться этого с помощью mpiexec, чтобы я мог параллельно обучать несколько моделей с разными входными данными?

Я нашел модель данных MPI с несколькими программами для одной программы, но не знаю соответствующих команд.

Я хочу запустить следующую строку параллельно среди вычислительных узлов в кластере.

python train.py arg > log.out # arg is the argument that differs for each node

Но, если я использую:

mpiexec train.py arg >log.out 

он будет запускать train.py только с одним и тем же аргументом командной строки: arg несколько раз параллельно.

Может ли кто-нибудь указать правильный способ сделать это? Спасибо!


person Tony L    schedule 01.10.2018    source источник
comment
проверьте комментарии в stackoverflow.com/questions/52324857/   -  person Gilles Gouaillardet    schedule 01.10.2018
comment
Спасибо, наше текущее решение использует сценарий оболочки для отправки всех похожих заданий в цикле while и передачи разных аргументов каждому исполняемому файлу задания. Это похоже на то, что делали фоновые процессы в этом посте.   -  person Tony L    schedule 01.10.2018
comment
Вам нужно, чтобы какие-либо данные из процесса train.py были переданы любому другому процессу train.py, или они все полностью независимы, и меняется только аргумент?   -  person Ed Smith    schedule 02.10.2018
comment
@EdSmith Каждый узел использует часть обучающих данных. Но между обработанными результатами каждого узла нет никакой зависимости.   -  person Tony L    schedule 04.10.2018


Ответы (2)


Один из способов добиться желаемого — создать скрипт верхнего уровня, mpi_train.py используя mpi4py. В задании MPI каждый процесс имеет уникальный ранг, и все они выполняют один и тот же код.

from mpi4py import MPI

comm = MPI.COMM_WORLD

print("Hello! I'm rank " + str(comm.rank))

с участием

mpiexec -n 4 python mpi_train.py

даст

Hello! I'm rank 0
Hello! I'm rank 1
Hello! I'm rank 3
Hello! I'm rank 2

Затем различные ранги можно использовать для чтения отдельного файла, в котором указаны аргументы. Таким образом, у вас будет что-то вроде,

#All code in train should be in functions or __name__ == "__main__"
import train
from mpi4py import MPI

def get_command_args_from_rank(rank):
     #Some code here to get args from unique rank no.

comm = MPI.COMM_WORLD

args = get_command_args_from_rank(comm.rank)

#Assuming the args can be passed to a run function
out = train.run(args)

Обратите внимание, что вы должны явно указать вывод для каждого процесса, например,

with open("log.out"+str(comm.rank)) as f:
    f.write(out)

в противном случае все отпечатки отправляются на стандартный вывод и становятся беспорядочными, поскольку порядок различных процессов не гарантируется.

person Ed Smith    schedule 02.10.2018
comment
это немного избыточно и неоптимально, так как может быть некоторый дисбаланс нагрузки, и mpiexec возвращается, когда завершается последний ранг (читай: все остальные ранги могут ничего не делать, и некоторые библиотеки MPI сжигают ЦП, делая это ). Использование массива заданий ИМХО намного проще и эффективнее. - person Gilles Gouaillardet; 03.10.2018
comment
Правда, массивы заданий выглядят лучшим решением для OP, может быть, стоит добавить в качестве ответа? Хотя разве это не фича PBS, а не MPI? Для балансировки нагрузки вы всегда можете добавить цикл поверх train.run, чтобы каждый процесс оставался занятым. - person Ed Smith; 03.10.2018
comment
Ну, дело в том, что mpiexec это не лучший способ одновременного запуска нескольких экземпляров последовательной программы. и да, массивы заданий — это функция диспетчера ресурсов (PBS, SLURM, LSF и др.), а не MPI. - person Gilles Gouaillardet; 03.10.2018

Спасибо за все комментарии и ответы. Вот что я сделал, чтобы получить окончательное решение:

Сначала у меня был сценарий bash для отправки задания в кластер в виде массива заданий с $PBS_ARRAYID для передачи разных аргументов командной строки для каждого задания:

#PBS -N ondemand/sys/myjobs/default
#PBS -l walltime=24:10:00
#PBS -l file=1gb
#PBS -l nodes=1:ppn=1:gpus=1:default
#PBS -l mem=40MB
#PBS -j oe
#PBS -A PAS0108
#PBS -o Job_array.out


# Move to the directory where the job was submitted
# run the following cmd in shell to submit the job in an array
# qsub -t 1-6 myjob.sh

cd $PBS_O_WORKDIR
cd $TMPDIR
# $PBS_ARRAYID can be used as a variable 

# copy data to local storage of the node
cp ~/code/2018_9_28_training_node_6_OSC/* $TMPDIR
cp -r ~/Datasets_1/Processed/PascalContext/ResNet_Output/ $TMPDIR
cp -r ~/Datasets_1/Processed/PascalContext/Truth/ $TMPDIR
cp -r ~/Datasets_1/Processed/PascalContext/Decision_Tree/ $TMPDIR

# currently in $TMPDIR, load modules
module load python/3.6 cuda
# using $PBS_ARRAYID as a variable to pass the corresponding node ID
python train_decision_tree_node.py $PBS_ARRAYID $TMPDIR  > training_log_${PBS_ARRAYID}

# saving logs
cp training_log ${HOME}/logs/${PBS_ARRAYID}_node_log/
cp my_results $PBS_O_WORKDIR

Я отправляю приведенный выше скрипт с командной строкой:

qsub -t 1-6 myjob.sh

Но я получил сообщение об ошибке от кластера, каким-то образом локальный каталог $TMPDIR не может быть распознан фактическим узлом в кластере, когда я запускаю скрипт.

Наконец, я использовал сценарий bash верхнего уровня для отправки каждого задания с другим аргументом командной строки в цикле while, и это сработало:

run_multiple_jobs.tcsh:

#!/usr/bin/env tcsh
set n = 1
while ( $n <= 5 )
    echo "Submitting job for concept node $n"
    qsub -v NODE=$n job.pbs
    @ n++
end

jobs.pbs:

#PBS -A PAS0108
#PBS -N node_${NODE}
#PBS -l walltime=160:00:00
#PBS -l nodes=1:ppn=1:gpus=1
#PBS -l mem=5GB
#PBS -m ae
#PBS -j oe

# copy data
cp -r ~/Datasets/Processed/PascalContext/Decision_Tree $TMPDIR
cp -r ~/Datasets/Processed/PascalContext/Truth $TMPDIR
cp -r ~/Datasets/Processed/PascalContext/ResNet_Output $TMPDIR

# move to working directory
cd $PBS_O_WORKDIR

# run program
module load python/3.6 cuda/8.0.44
python train_decision_tree_node.py ${NODE} $TMPDIR $HOME

# run with run_multiple_jobs.tcsh script
person Tony L    schedule 04.10.2018