Начало работы с HPX руководство
предполагает, что вы используете PBS или slurm. Они могут быть довольно распространены в сообществе HPC, но как разработчик я более привык к сценарию, здесь есть пара машин, на которые можно устанавливать вещи.
Не сразу очевидно, нужен ли планировщик типа slurm для использования нескольких физических машин или просто удобен для управления кластером.
Я знаю, что вы можете имитировать несколько населенных пунктов, используя флаг -l при запуске приложения HPX (см., Например, этот вопрос) я хочу запустить одно и то же приложение на 2 узлах и заставить их общаться друг с другом.
Какой минимум необходим, чтобы сказать HPX:
Вот еще один компьютер с этим IP-адресом, на который вы можете отправлять задания?
В качестве альтернативы, какова минимальная конфигурация грязи для достижения этой стадии?
Установить slurm было легко, если бы найти простой пример с двумя узлами. эта ссылка на подкаст может помочь
Я также предполагаю, что порт посылки HPX будет работать только через TCP, не устанавливая ничего лишнего (например, MPI). Это правильно?
Обновить
Я думаю, что все ближе, но я все еще что-то упускаю.
Сначала я использую пример hello_world. Может быть, это слишком просто для теста 2 узла?
Я надеюсь на вывод, похожий на запуск 2 локаций на одном узле:
APP=$HPX/bin/hello_world
$APP --hpx:node 0 --hpx:threads 4 -l2 &
$APP --hpx:node 1 --hpx:threads 4
образец вывода:
привет мир из ОС-нити 2 на местности 0 привет мир из OS-нить 0 на местности 0 привет мир из ОС-нить 1 на местности 1 привет мир из ОС-нить 3 на местности 1 привет мир из ОС-нити 2 на местности 1 привет мир из ОС-нить 1 на местности 0 привет мир из ОС-нити 0 на местности 1 привет мир из ОС-нить 3 на местности 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» & Я получил:
> кошка hpx.log (T00000000 /----------------.----/----------------) P ------- - / ----------------.---- 14: 18.29.042 [0000000000000001] [ERR] создано исключение: HPX (успех) (T00000000 /----------------.----/----------------) P ------- - / ----------------.---- 14: 18.29.042 [0000000000000002] [ERR] создано исключение: HPX (успех)
на обеих машинах. Я не уверен, как это интерпретировать.
Я пробовал несколько других вариантов, таких как —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
хвост узла0.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 прослушать (7, 128) = 0 15:13:31 ioctl (7, FIONBIO, [1]) = 0 15:13:31 accept (7, 0, NULL) = -1 EAGAIN (ресурс временно недоступен) ... 15:13:32 mprotect (0x7f12b2bff000, 4096, PROT_NONE) = 0 15:13:32 клон (child_stack = 0x7f12b33feef0, флаги = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID, parent_tidptr = 0x7f12b33ff9d0, 0x7f12b33ff700 = TLS, 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 прослушать (7, 128) = 0 16829 15:13:32 ioctl (7, FIONBIO, [1]) = 0 16829 15:13:32 accept (7, 0, NULL) = -1 EAGAIN (ресурс временно недоступен) 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 запись (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 сокет (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 сокет (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 (соединение отказано) 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 (Тайм-аут соединения) 22050 15:12:46 futex (0x7fcc9cc204d8, FUTEX_WAKE_PRIVATE, 1) = 0 22050 15:12:46 close (12) = 0 22050 15:12:46 сокет (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 (соединение отказано) 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.
Угадай, что! Изменение, которое исправило это. Так что технически первый ответ был правильным, и я просто тупой.
Я ожидал бы ошибку от парсера параметров командной строки, но я предполагаю, что когда вы выполняете массивно параллельную среду выполнения, у вас не может быть всего :).
Спасибо всем за помощь.
Вариант 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 для использования.
Другими словами,
--hpx:hpx=node0:7910
) и порт, где будет прослушиваться основной экземпляр механизма активного глобального адресного пространства (AGAS) (это будет использоваться для других узлов для установления начального соединения (--hpx:agas=node0:7910
). Вы также указываете, что в целом 2
населенные пункты будут подключаться (--hpx:localities=2
).--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
это запустит два экземпляра вашего приложения на текущем вычислительном узле.
Я не могу прокомментировать существующий ответ, поэтому я повторю некоторую информацию из ответа @hkaiser: на узле консоли / мастера или того, что мы обычно называем 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 parcelport, добавьте
-Ihpx.parcel.tcp.enable=1 -Ihpx.parcel.mpi.enable=0
в вашей командной строке (на всех узлах), чтобы HPX выбирал TCP parcelport.