2017-01-27 6 views
3

У меня возникла проблема, когда мне нужно запустить тот же скрипт, но с разными входными аргументами.SLURM sbatch job array для того же скрипта, но с разными входными аргументами, выполняемыми параллельно

Скажем, у меня есть сценарий myscript.py -p <par_Val> -i <num_trial>, где мне нужно рассмотреть N различные par_values (между x0 и x1) и M испытаний для каждого значения par_values.

Каждое испытание M таково, что оно почти достигает временного диапазона кластера, в котором я работаю (и у меня нет привилегий, чтобы изменить это). Поэтому на практике мне нужно запустить NxM независимых рабочих мест.

Поскольку каждые из пакетных заданий имеют такую ​​же конфигурацию узла/центральный процессор и вызывают тот же питон скрипт, для изменения входных параметров, в принципе, за исключением того, в псевдо-языке, который я должен иметь sbatch сценарий, который должен сделать что-то вроде:

#!/bin/bash 
#SBATCH --job-name=cv_01 
#SBATCH --output=cv_analysis_eis-%j.out 
#SBATCH --error=cv_analysis_eis-%j.err 
#SBATCH --partition=gpu2 
#SBATCH --nodes=1 
#SBATCH --cpus-per-task=4 

for p1 in 0.05 0.075 0.1 0.25 0.5 
do 
    for i in {0..150..5} 
    do 
     python myscript.py -p p1 -v i 
    done 
done 

где каждый вызов сценария сам по себе является пакетным заданием. Глядя на sbatch doc, вариант -a --array кажется многообещающим. Но в моем случае мне нужно изменить входные параметры для каждого скрипта NxM, который у меня есть. Как я могу это сделать? Я бы не хотел писать NxM пакетных скриптов, а затем перечислил их в файле txt, как это было предложено this post. Не предлагаемое решение here кажется идеальным, так как это имеет место в imho массива заданий. Кроме того, я хотел бы убедиться, что все сценарии NxM запускаются одновременно, а вызывающий выше скрипт заканчивается сразу после этого, так что он не будет сталкиваться с ограничением по времени, и вся моя работа будет завершена системой и остаются неполными (тогда как, поскольку каждое из заданий NxM находится в таком пределе, если они выполняются параллельно, но независимы, этого не произойдет).

ответ

2

Лучшим подходом является использование рабочих массивов.

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

код будет выглядеть следующим образом (непроверенные):

#!/bin/bash 
#SBATCH --job-name=cv_01 
#SBATCH --output=cv_analysis_eis-%j-%a.out 
#SBATCH --error=cv_analysis_eis-%j-%a.err 
#SBATCH --partition=gpu2 
#SBATCH --nodes=1 
#SBATCH --cpus-per-task=4 
#SBATCH -a 0-150:5 

python myscript.py -p $1 -v $SLURM_ARRAY_TASK_ID 

и вы представите его:

sbatch my_jobscript.sh 0.05 
sbatch my_jobscript.sh 0.075 
... 

Другой подход заключается в определении всех параметров p1 в массиве Баш и представить NxM (непроверенные)

#!/bin/bash 
#SBATCH --job-name=cv_01 
#SBATCH --output=cv_analysis_eis-%j-%a.out 
#SBATCH --error=cv_analysis_eis-%j-%a.err 
#SBATCH --partition=gpu2 
#SBATCH --nodes=1 
#SBATCH --cpus-per-task=4 
#Make the array NxM 
#SBATCH -a 0-150 

PARRAY=(0.05 0.075 0.1 0.25 0.5)  

#p1 is the element of the array found with ARRAY_ID mod P_ARRAY_LENGTH 
p1=${PARRAY[`expr $SLURM_ARRAY_TASK_ID % ${#PARRAY[@]}`]} 
#v is the integer division of the ARRAY_ID by the lenght of 
v=`expr $SLURM_ARRAY_TASK_ID/${#PARRAY[@]}` 
python myscript.py -p $p1 -v $v 
+0

Спасибо это именно то, что я искал , Однако, прежде чем я его одобрю, во втором примере, который вы предоставляете, я не убежден аргументом '$ 1' в' expr', когда вы назначаете 'p1'. Не могли бы вы пояснить это. Это не имеет для меня никакого смысла, так как afaik $ относится к входным аргументам ... – maurizio

+0

Хорошо, ваш ответ правильный, с малой опечаткой на присваивание 'p1', который должен быть вместо' p1 = $ {PARRAY [ 'expr $ SLURM_ARRAY_TASK_ID% $ {# PARRAY [@]}']} '. – maurizio

+0

Вы правы. Я исправлю это сейчас –

0

Если вы используете массивы работы SLURM, вы можете линеаризовать индекс своих двух fo r, а затем выполнить сравнение индекса цикла и идентификатора задачи массива:

#!/bin/bash 
#SBATCH --job-name=cv_01 
#SBATCH --output=cv_analysis_eis-%j.out 
#SBATCH --error=cv_analysis_eis-%j.err 
#SBATCH --partition=gpu2 
#SBATCH --nodes=1 
#SBATCH --cpus-per-task=4 
#SBATCH -a 0-154 

# NxM = 5 * 31 = 154 

p1_arr=(0.05 0.075 0.1 0.25 0.5) 

# SLURM_ARRAY_TASK_ID=154 # comment in for testing 

for ip1 in {0..4} # 5 steps 
do 
    for i in {0..150..5} # 31 steps 
    do 
     let task_id=$i/5+31*$ip1 

     # printf $task_id"\n" # comment in for testing 

     if [ "$task_id" -eq "$SLURM_ARRAY_TASK_ID" ] 
     then 
      p1=${p1_arr[ip1]} 
      # printf "python myscript.py -p $p1 -v $i\n" # comment in for testing 
      python myscript.py -p $p1 -v $i\n 
     fi 
    done 
done 

Этот ответ очень похож на Карла. Поэтому я предпочел бы писать это как комментарий, но не имел достаточной репутации.

0

Согласно this page, массивы заданий несут значительные накладные расходы:

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

Эта страница предоставляет несколько примеров для запуска вашей работы, используя как массивы, так и «упакованные задания».

Если вы не хотите/не должны указывать ресурсы для своей работы, вот еще один подход: я не уверен, что это утилита, предназначенная Slurm, но она работает, и сценарий отправки выглядит немного лучше, так как нам не нужно линеаризовать индексы, чтобы поместить его в парадигму массива заданий. Плюс он хорошо работает с вложенными петлями произвольной глубины.

Выполнить это прямо как сценарий оболочки:

#!/bin/bash 
FLAGS="--ntasks=1 --cpus-per-task=1" 
for i in 1 2 3 4 5; do 
     for j in 1 2 3 4 5; do 
      for k in 1 2 3 4 5; do 
       sbatch $FLAGS testscript.py $i $j $k 
     done 
    done 
done 

, где вам нужно, чтобы убедиться, что testscript.py указывает на правильный интерпретатор в первой строке с помощью #! например

#!/usr/bin/env python 
import time 
import sys 
time.sleep(5) 
print "This is my script" 
print sys.argv[1], sys.argv[2], sys.argv[3] 

В качестве альтернативы (непроверенные), вы можете использовать --wrap флаг, как этот

sbatch $FLAGS --wrap="python testscript.py $i $j $k" 

, и вы не будете нуждаться в #!/usr/bin/env python линии в testscript.py