Моя программа использует MPI + pthreads, где n-1 MPI-процессы являются чистым кодом MPI, тогда как единственный процесс MPI использует pthreads. Последний процесс содержит всего 2 потока (основной поток и pthread). Предположим, что кластер HPC, на котором я хочу запустить эту программу, состоит из вычислительных узлов, каждый из которых имеет 12 ядер. Как мне написать пакетный сценарий, чтобы максимально использовать оборудование?

Ниже приведен мой пакетный сценарий, который я написал. Я использую экспорт OMP_NUM_THREADS = 2, потому что последний процесс MPI имеет 2 потока и должен предполагать, что у других также есть 2 потока.

Затем я выделяю 6 процессов MPI на узел, поэтому каждый узел может запускать 6xOMP_NUM_THREADS = 12 (= количество ядер на каждом узле) потоков, несмотря на то, что все процессы MPI, кроме одного, имеют 1 поток.

#BSUB -J LOOP.N200.L1000_SIMPLE_THREAD
#BSUB -o LOOP.%J
#BSUB -W 00:10
#BSUB -M 1024
#BSUB -N
#BSUB -a openmpi
#BSUB -n 20
#BSUB -m xxx
#BSUB -R "span[ptile=6]"
#BSUB -x

export OMP_NUM_THREADS=2

Как мне написать лучший сценарий для этого?

0
cpp_noname 28 Окт 2014 в 18:12

2 ответа

Лучший ответ

Следующее должно работать, если вы хотите, чтобы последний ранг был гибридным:

#BSUB -n 20
#BSUB -R "span[ptile=12]"
#BSUB -x

$MPIEXEC $FLAGS_MPI_BATCH -n 19 -x OMP_NUM_THREADS=1 ./program : \
         $FLAGS_MPI_BATCH -n 1  -x OMP_NUM_THREADS=2 ./program

Если вы хотите, чтобы ранг 0 был гибридным, просто переключите две строки:

$MPIEXEC $FLAGS_MPI_BATCH -n 1  -x OMP_NUM_THREADS=2 ./program : \
         $FLAGS_MPI_BATCH -n 19 -x OMP_NUM_THREADS=1 ./program

Это использует возможность Open MPI для запуска программ MIMD.

Вы упоминаете, что в вашем гибридном ранге используются потоки POSIX, но при этом вы устанавливаете переменную среды, связанную с OpenMP. Если вы на самом деле не используете OpenMP, вам вообще не нужно устанавливать OMP_NUM_THREADS, и этой простой команды mpiexec должно хватить:

$MPIEXEC $FLAGS_MPI_BATCH ./program

(на случай, если мое предположение об учебном заведении, в котором вы учитесь или работаете, окажется неверным, удалите $FLAGS_MPI_BATCH и замените $MPIEXEC на mpiexec)

2
Hristo Iliev 31 Окт 2014 в 10:56
Большое спасибо !!!. Значит ли это, что два потока последнего ранга будут выполняться на любых двух доступных ядрах второго вычислительного узла? Без дополнительной информации о двух потоках возможно ли, что LSF может запланировать эти два потока на одном и том же ядре процессора?
 – 
cpp_noname
31 Окт 2014 в 13:53
LSF обычно назначает слоты, а не ядра. Связывание (то есть ограничение планирования процессов определенными логическими ЦП) обычно выполняется реализацией MPI или средой выполнения OpenMP (или обоими для гибридных программ).
 – 
Hristo Iliev
31 Окт 2014 в 16:24

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

Я прочитал ваш запрос

#BSUB -n 20
#BSUB -R "span[ptile=6]"

Как, всего 20 задач, по 6 задач на узел. Это означает, что вы получите 4 узла. Что кажется пустой тратой, поскольку вы заявили, что каждый узел имеет 12 ядер.

Как насчет использования всех ядер на узлах, поскольку вы запросили эксклюзивные хосты (-x)

#BSUB -x
#BSUB -n 20
#BSUB -R "span[ptile=12]"

export OMP_NUM_THREADS=2

Таким образом, вы знаете ранг

  • 0..11 находится на первом хосте
  • 12..19 находится на втором хосте

Где у второго хоста есть свободные слоты, чтобы использовать OpenMP ранга 19.

Конечно, если вы попадаете на еще более забавную должность, LSF позволяет вам определить место трудоустройства. Используя LSB_PJL_TASK_GEOMETRY.

Допустим, у вас было 25 задач MPI с рангом 5 с использованием 12 ядер.

#BSUB -x
#BSUB -n 25
#BSUB -R "span[ptile=12]"

export LSB_PJL_TASK_GEOMETRY="{(0,1,2,3,4,6,7,8,9,10,11,12)\
                               (13,14,15,16,17,18,19,20,21,22,23,24)\
                               (5)}"

Таким образом, задача 5 получит собственный узел.

1
Timothy Brown 31 Окт 2014 в 00:23
Большое спасибо. Но я все еще не совсем понимаю использование #BSUB -n. Используется ли он для резервирования заданного количества аппаратных вычислительных слотов или для указания количества параллельных процессов? И делает ли #BSUB -n различие между потоками и процессами MPI?
 – 
cpp_noname
31 Окт 2014 в 01:35
@cpp_noname, -n указывает количество слотов. В вашем случае каждый вычислительный узел предоставляет 12 слотов, и это соответствует количеству ядер ЦП на узле (но обратите внимание, что слоты не сопоставляются напрямую с ядрами). Каждое задание может использовать свои слоты по своему усмотрению. Грубо говоря, задания MPI запускают один процесс в каждом слоте, а задания OpenMP запускают один поток в каждом слоте.
 – 
Hristo Iliev
31 Окт 2014 в 11:02
@HristoIliev, предположим, что моя программа использует 6 процессов MPI, каждый из которых имеет 3 потока. Всего у меня 6x3=18 параллельных потоков. Тогда каким должно быть n? #BSUB -n 6 или #BSUB -n 18
 – 
cpp_noname
31 Окт 2014 в 13:59
-n 6 -R "span[ptile=4]" -x, чтобы получить 6 слотов, иметь 4 процесса MPI на узел и иметь исключительно узлы. Это приведет к следующему распределению: 4x3+2x3 (MPI обрабатывает x потоков). Обратите внимание, что это относится только к потокам, интенсивно использующим ЦП. В кластерах InfiniBand Open MPI порождает два дополнительных потока на каждый процесс. Эти два процессора мало используют ЦП и поэтому могут совместно использовать одно ядро ​​с основным потоком, и вам не нужно запрашивать для них специальные слоты.
 – 
Hristo Iliev
31 Окт 2014 в 16:27