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

руководство по началу работы с HPX предполагает, что вы с использованием PBS или slurm. Это может быть довольно распространено в сообществе HPC, но как разработчик я больше привык к сценарию, в котором есть пара машин, на которые вы можете установить что-то.

Не сразу очевидно, требуется ли такой планировщик, как slurm, для использования нескольких физических машин или он просто удобен для управления кластером.

Я знаю, что вы можете имитировать несколько местоположений, используя флаг -l при запуске приложения HPX (см., например, этот вопрос) я хочу запустить одно и то же приложение на 2 узлах и заставить их общаться друг с другом.

Каков минимум, необходимый для того, чтобы сообщить HPX:
Есть еще одна машина с таким IP-адресом, на которую вы можете отправлять задачи?

В качестве альтернативы, какова минимальная конфигурация slarm для достижения этой стадии?

Установить slurm было легко, найти простой пример с двумя узлами не так сложно. Хотя эта ссылка на подкаст может помощь

Я также предполагаю, что порт посылок HPX будет работать только через TCP без установки чего-либо дополнительного (например, MPI). Это правильно?


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

APP=$HPX/bin/hello_world
$APP --hpx:node 0 --hpx:threads 4 -l2 &
$APP --hpx:node 1 --hpx:threads 4 

образец вывода:

hello world from OS-thread 2 on locality 0
hello world from OS-thread 0 on locality 0
hello world from OS-thread 1 on locality 1
hello world from OS-thread 3 on locality 1
hello world from OS-thread 2 on locality 1
hello world from OS-thread 1 on locality 0
hello world from OS-thread 0 on locality 1
hello world from OS-thread 3 on locality 0

но когда я пытаюсь удалить его, оба процесса зависают:

$APP --hpx:localities=2 --hpx:agas=$NODE0:7910 --hpx:hpx=$NODE0:7910 --hpx:threads 4 &
ssh $NODE1 $APP --hpx:localities=2 --hpx:agas=$NODE0:7910 --hpx.hpx=$NODE1:7910 --hpx:threads 4 

Я открыл порт 7910 на обеих машинах. Путь к $APP одинаков на обоих узлах. Я не уверен, как проверить, разговаривает ли второй процесс с сервером agas.

Если я использую "--hpx:debug-agas-log=agas.log" и "--hpx:debug-hpx-log=hpx.log", я получаю:

>cat hpx.log 
(T00000000/----------------.----/----------------) P--------/----------------.---- 14:18.29.042 [0000000000000001]    [ERR] created exception: HPX(success)
(T00000000/----------------.----/----------------) P--------/----------------.---- 14:18.29.042 [0000000000000002]    [ERR] created exception: HPX(success)

на обеих машинах. Я не уверен, как это интерпретировать.

Я пробовал несколько других вариантов, таких как --hpx:run-agas-server (я думаю, что это, возможно, подразумевается при использовании --hpx:agas=)

я тоже пробовал

ssh $NODE1 $APP --hpx:nodes="$NODE0 $NODE1" &
$APP --hpx:nodes="$NODE0 $NODE1"

как было предложено другим (теперь удаленным?) ответом без везения.


обновление 2

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

echo "start server on agas master: node0=$NODE0"
strace -o node0.strace $APP \
 --hpx:localities=2 --hpx:agas=$NODE0:7910 --hpx:hpx=$NODE0:7910 --hpx:threads 4 &
cat agas.log hpx.log
echo "start worker on slave: node1=$NODE1"
ssh $NODE1 \
strace -o node1.strace $APP \
--hpx:worker --hpx:agas=$NODE0:7910 --hpx.hpx=$NODE1:7910 
echo "done"
exit 0

хвост node0.strace:

15:13:31 bind(7, {sa_family=AF_INET, sin_port=htons(7910), sin_addr=inet_addr("172.29.0.160")}, 16) = 0 
15:13:31 listen(7, 128)                 = 0 
15:13:31 ioctl(7, FIONBIO, [1])         = 0 
15:13:31 accept(7, 0, NULL)             = -1 EAGAIN (Resource temporarily unavailable) 
...
15:13:32 mprotect(0x7f12b2bff000, 4096, PROT_NONE) = 0 
15:13:32 clone(child_stack=0x7f12b33feef0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7f12b33ff9d0, tls=0x7f12b33ff700, child_tidptr=0x7f12b33ff9d0) = 22394 
15:13:32 futex(0x7ffe2c5df60c, FUTEX_WAIT_PRIVATE, 1, NULL) = 0 
15:13:32 futex(0x7ffe2c5df5e0, FUTEX_WAKE_PRIVATE, 1) = 0 
15:13:32 futex(0x7ffe2c5df4b4, FUTEX_WAIT_PRIVATE, 1, NULL

хвост node1.strace:

6829 15:13:32 bind(7, {sa_family=AF_INET, sin_port=htons(7910), sin_addr=inet_addr("127.0.0.1")}, 16) = 0 
16829 15:13:32 listen(7, 128)           = 0 
16829 15:13:32 ioctl(7, FIONBIO, [1])   = 0 
16829 15:13:32 accept(7, 0, NULL)       = -1 EAGAIN (Resource temporarily unavailable) 
16829 15:13:32 uname({sys="Linux", node="kmlwg-tddamstest3.grpitsrv.com", ...}) = 0 
16829 15:13:32 eventfd2(0, O_NONBLOCK|O_CLOEXEC) = 8 
16829 15:13:32 epoll_create1(EPOLL_CLOEXEC) = 9 
16829 15:13:32 timerfd_create(CLOCK_MONOTONIC, 0x80000 /* TFD_??? */) = 10 
16829 15:13:32 epoll_ctl(9, EPOLL_CTL_ADD, 8, {EPOLLIN|EPOLLERR|EPOLLET, {u32=124005464, u64=140359655238744}}) = 0 
16829 15:13:32 write(8, "\1\0\0\0\0\0\0\0", 8) = 8 
16829 15:13:32 epoll_ctl(9, EPOLL_CTL_ADD, 10, {EPOLLIN|EPOLLERR, {u32=124005476, u64=140359655238756}}) = 0 
16829 15:13:32 futex(0x7fa8006f2d24, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x7fa8006f2d20, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1 
16830 15:13:32  )    = 0 
16829 15:13:32 socket(PF_INET, SOCK_STREAM, IPPROTO_TCP 
16830 15:13:32 futex(0x7fa8076432f0, FUTEX_WAKE_PRIVATE, 1) = 0 
16829 15:13:32  )   = 11 
16830 15:13:32 epoll_wait(9,  
16829 15:13:32 epoll_ctl(9, EPOLL_CTL_ADD, 11, {EPOLLIN|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET, {u32=124362176, u64=140359655595456}} 
16830 15:13:32  {{EPOLLIN, {u32=124005464, u64=140359655238744}}}, 128, -1) = 1 
16829 15:13:32  ) = 0 
16830 15:13:32 epoll_wait(9,  
16829 15:13:32 connect(11, {sa_family=AF_INET, sin_port=htons(7910), sin_addr=inet_addr("172.29.0.160")}, 16 
16830 15:13:32  {{EPOLLHUP, {u32=124362176, u64=140359655595456}}}, 128, -1) = 1 
16830 15:13:32 epoll_wait(9,  

Если я делаю strace -f на мастере, его дочерний процесс зацикливается, делая что-то вроде этого:

22050 15:12:46 socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 12 
22050 15:12:46 epoll_ctl(5, EPOLL_CTL_ADD, 12, {EPOLLIN|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET, {u32=2395115776, u64=140516545171712}}) = 0 
22041 15:12:46  {{EPOLLHUP, {u32=2395115776, u64=140516545171712}}}, 128, -1) = 1 
22050 15:12:46 connect(12, {sa_family=AF_INET, sin_port=htons(7910), sin_addr=inet_addr("127.0.0.1")}, 16 
22041 15:12:46 epoll_wait(5,  
22050 15:12:46  )  = -1 ECONNREFUSED (Connection refused) 
22041 15:12:46  {{EPOLLHUP, {u32=2395115776, u64=140516545171712}}}, 128, -1) = 1 
22050 15:12:46 futex(0x7fcc9cc20504, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME, 1703, {1455808366, 471644000}, ffffffff 
22041 15:12:46 epoll_wait(5,  
22050 15:12:46  )    = -1 ETIMEDOUT (Connection timed out) 
22050 15:12:46 futex(0x7fcc9cc204d8, FUTEX_WAKE_PRIVATE, 1) = 0 
22050 15:12:46 close(12)                = 0 
22050 15:12:46 socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 12 
22050 15:12:46 epoll_ctl(5, EPOLL_CTL_ADD, 12, {EPOLLIN|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET, {u32=2395115776, u64=140516545171712}}) = 0 
22050 15:12:46 connect(12, {sa_family=AF_INET, sin_port=htons(7910), sin_addr=inet_addr("127.0.0.1")}, 16 
22041 15:12:46  {{EPOLLHUP, {u32=2395115776, u64=140516545171712}}}, 128, -1) = 1 
22050 15:12:46  )  = -1 ECONNREFUSED (Connection refused) 
22041 15:12:46 epoll_wait(5,  
22050 15:12:46 futex(0x7fcc9cc20504, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME, 1705, {1455808366, 572608000}, ffffffff 
22041 15:12:46  {{EPOLLHUP, {u32=2395115776, u64=140516545171712}}}, 128, -1) = 1 

Обновление 3

Проницательные из вас могли заметить, что в обновлении 2 я случайно написал --hpx.hpx вместо --hpx:hpx. Угадай, что! Изменение этого исправило это. Так что технически первый ответ был правильным, а я просто тупой. Я бы ожидал ошибки от синтаксического анализатора параметров командной строки, но я думаю, когда вы создаете массово параллельную среду выполнения, у вас не может быть всего :).

Спасибо всем за помощь.


person Bruce Adams    schedule 12.02.2016    source источник
comment
Спасибо, что сообщили нам, что --hpx.hpx не выдает сообщения об ошибке (или, по крайней мере, предупреждения). Я пока не уверен, как это решить (это было обдуманное дизайнерское решение — по загадочным причинам), но я создал тикет в качестве напоминания нам, чтобы мы рассмотрели это (github.com/STEllAR-GROUP/hpx/issues/1995).   -  person hkaiser    schedule 21.02.2016
comment
Рад видеть, что ты на высоте. Я собирался добавить билет сам.   -  person Bruce Adams    schedule 22.02.2016


Ответы (2)


Вариант 1: При использовании TCP/IP для сетевого уровня (обычно по умолчанию):

Чтобы приложение HPX могло найти все подключенные узлы, за пределами пакетных сред должна быть предоставлена ​​следующая информация:

locality 0:
./yourapp --hpx:localities=2 --hpx:agas=node0:7910 --hpx:hpx=node0:7910 

locality 1:
./yourapp --hpx:agas=node0:7910 --hpx:hpx=node1:7910 --hpx:worker

Где node0 и node1 — это имена хостов этих узлов, а 7910 — это (произвольный) порт TCP/IP для использования.

Другими словами,

  • на node0 вы указываете порт, на котором HPX будет прослушивать входящие сообщения на этом узле (--hpx:hpx=node0:7910), и порт, на котором будет прослушиваться основной экземпляр механизма Active Global Address Space (AGAS) (он будет использоваться для других узлов для установления начального подключение (--hpx:agas=node0:7910). Вы также указываете, что всего будет подключено 2 населенных пунктов (--hpx:localities=2).
  • на узле 1 (и на всех других узлах, которые вы хотите подключить) вы указываете порт, на котором HPX будет прослушивать входящие сообщения на этом узле (--hpx:hpx=node1:7910), и порт, по которому можно будет связаться с основным механизмом AGAS в местоположении 0 (--hpx:agas=node0:7910). Вы также указываете, что эта локация является рабочей (а не «консольной»), что делается с помощью параметра командной строки --hpx:worker.

Обратите внимание, что все эти параметры имеют однобуквенные сокращения (--hpx:localities == -l, --hpx:hpx == -x, --hpx:agas == -a и --hpx:worker == -w).

Вы также можете запускать несколько локаций на одном физическом вычислительном узле (или на своем ноутбуке). В этом случае немного менее утомительно указывать вещи, например:

./yourapp -l2 -0 &
./yourapp -1

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

Вариант 2: При использовании MPI (требуется специальная конфигурация времени сборки):

Просто используйте mpirun для выполнения вашего приложения. Он выберет настройки либо из вашей пакетной среды, либо будет использовать параметры командной строки для запуска вещей. Например:

mpirun -N1 -np2 ./yourapp

это запустит два экземпляра вашего приложения на текущем вычислительном узле.

person hkaiser    schedule 13.02.2016
comment
Спасибо. Я думаю, что это делает меня намного ближе, но я все еще застрял. Я обновил вопрос, чтобы отразить, где я сейчас нахожусь, поскольку место для комментариев слишком мало. - person Bruce Adams; 15.02.2016
comment
Единственное, что я забыл упомянуть в своем ответе, это то, что всем населенным пунктам, которые не являются населенными пунктами 0, нужно сказать, что они являются рабочими населенными пунктами. Вы делаете это, добавляя флаг -w в командную строку. Я обновил свой ответ соответственно. - person hkaiser; 17.02.2016
comment
Кажется, это не имело для меня никакого значения. Я предполагаю, что рабочий должен подразумеваться, если сервер agas находится на другой машине? Я добавил некоторые системные трассировки на случай, если это загорится. Есть ли хороший способ пропинговать сервер agas, чтобы проверить, работает ли он? - person Bruce Adams; 18.02.2016
comment
Проблема здесь, кажется, в спецификациях порта. Если вы полностью опустите их (избавьтесь от :7910 для спецификации узла), это сработает для меня. Похоже, есть ошибка в последовательности инициализации. Если порты не указаны, мы прослушиваем порт 7910 + locality_id для входящих соединений. По какой-то причине это не переопределяется при явном указании порта. если вы передадите --hpx:hpx=$NODE1:7911 для второго местоположения (и сохраните все остальное без изменений), похоже, это сработает. - person Thomas Heller; 19.02.2016
comment
Вот команды, которые я использовал: $APP --hpx:localities=2 --hpx:agas=$NODE0:7910 --hpx:hpx=$NODE0:7910 & ssh $NODE1 $APP --hpx:localities=2 --hpx:agas=$NODE0:7910 --hpx:hpx=$NODE1:7911 --hpx:рабочий - person Thomas Heller; 19.02.2016
comment
@Thomas Heller: разве это не то, что я предложил выше? - person hkaiser; 19.02.2016
comment
@hkaiser: нет, разница в номере порта, используемом для местоположения 1. Как указал Джон, похоже, это работает при использовании IP-адресов вместо имен хостов. - person Thomas Heller; 19.02.2016

Я не могу прокомментировать существующий ответ, поэтому я повторю некоторую информацию из ответа @hkaiser: на узле console/master или на том, что мы обычно считаем rank0, вы должны использовать команду вида

`bin/hello_world -l2 --hpx:agas=xx.xx.xx.AA:7910 --hpx:hpx=xx.xx.xx.AA:7910 `

и на рабочем узле вы должны использовать

`bin/hello_world --hpx:agas=xx.xx.xx.AA:7910 --hpx:hpx=xx.xx.xx.BB:7910 --hpx:worker`

Но важно, чтобы IP-адрес, который вы используете, был возвращен внешней сетью узлов, а не внутренней сетью (в случае нескольких NIC/IP-адресов). Чтобы убедиться, что я получаю правильный адрес, я обычно запускаю команду

ip route get 8.8.8.8 | awk 'NR==1 {print $NF}'

на каждом узле и использовать выходные данные при тестировании.

Обратите внимание, что эта спецификация IP-адреса необходима только тогда, когда вы запускаете задания вручную, не используя mpirun или srun для запуска заданий, так как эти команды будут запускать задания на узлах, выделенных пакетной системой и коммуникацией. будет корректно обрабатываться внутренними компонентами HPX. При использовании пакетной системы, но в любом случае при запуске заданий вручную (например, из интерактивной оболочки, вы обнаружите, что добавление параметра --hpx:ignore-batch-env в вашу командную строку поможет предотвратить получение HPX нежелательных параметров.

Сегодня утром я попытался выполнить git commit 0c3174572ef5d2c из репозитория HPX, и мой результат выглядит следующим образом.

Главный узел

bin/hello_world --hpx:agas=148.187.68.38:7910 --hpx:hpx=148.187.68.38:7910 -l2 --hpx:threads=4 hello world from OS-thread 3 on locality 1 hello world from OS-thread 6 on locality 1 hello world from OS-thread 2 on locality 1 hello world from OS-thread 7 on locality 1 hello world from OS-thread 5 on locality 1 hello world from OS-thread 0 on locality 1 hello world from OS-thread 4 on locality 1 hello world from OS-thread 1 on locality 1 hello world from OS-thread 0 on locality 0 hello world from OS-thread 2 on locality 0 hello world from OS-thread 1 on locality 0 hello world from OS-thread 3 on locality 0

Рабочий узел

bin/hello_world --hpx:agas=148.187.68.38:7910 --hpx:hpx=148.187.68.36:7910 --hpx:worker --hpx:threads=8

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

Парселпорт

если вы скомпилировали с поддержкой MPI (например) и хотите быть уверенным, что используется порт посылки TCP, то добавьте

-Ihpx.parcel.tcp.enable=1 -Ihpx.parcel.mpi.enable=0

в вашу командную строку (на всех узлах), чтобы HPX выбрал порт посылки TCP.

person biddisco    schedule 19.02.2016