MPI_Send застрять при выполнении с разными узлами
У меня есть очень простая программа MPI, в которой узел 0 отправляет символ на узел 1, но отправка и получение зависают, когда я использую две или более разных машин. Программа отлично работает, когда я использую несколько процессов только на одной машине. Кажется, это проблема со связью, но я не могу понять, что это такое.....
Вот код:
int main(int argc, char *argv[]) {
int numtasks, rank, tag = 1;
char inmsg, outmsg = 'x';
MPI_Status stat;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if ( rank == 0 ) {
MPI_Send(&outmsg, 1, MPI_CHAR, 1, tag, MPI_COMM_WORLD);
}
else if ( rank == 1 ) {
MPI_Recv(&inmsg, 1, MPI_CHAR, 0, tag, MPI_COMM_WORLD, &stat);
}
MPI_Finalize();
}
Кроме того, вот несколько важных замечаний:
- Я использую кластер из 2 виртуальных машин в Google Compute Engine: mpi-test-uaiw и mpi -test-130b;
- Я уже настроил ssh без пароля между двумя виртуальными машинами, то есть из mpi-test-uaiw я могу просто набрать ssh mpi-test-130b, и он отлично работает (работает и обратное);
- Простой "Hello World", использующий MPI, работает с этим кластером, но он не содержит никаких операций отправки или получения;
- Брандмауэр деактивирован.
Любая помощь будет оценена. Спасибо!
1 ответ
Я нашел решение своей проблемы:
Я использовал MPICH и запустил мою программу с mpirun. Проблема в том, что mpich использовал неправильный сетевой интерфейс. Каждый узел имеет два интерфейса: lo и ens4. Из того, что я видел в других статьях, похоже, что lo используется для передачи данных от одного узла к себе, а ens4 используется для связи с другими узлами. Я проверил это с помощью следующих команд ping:
$ ifconfig -a
: показывает доступные интерфейсы;- Из mpi-test-uaiw:
$ ping -I lo mpi-test-130b
-> ОШИБКИ - Из mpi-test-uaiw:
$ ping -I ens4 mpi-test-130b
-> УСПЕХ - Из mpi-test-uaiw:
$ ping -I lo mpi-test-uaiw
-> УСПЕХ - Из mpi-test-uaiw:
$ ping -I ens4 mpi-test-uaiw
-> ОШИБКИ
Одним из возможных решений является использование mpirun --mca btl_tcp_if_include ens4, чтобы убедиться, что mpirun использует интерфейс ens4 для связи с другим узлом. Но это не сработало для меня, поскольку MPICH не распознает параметр --mca. Поэтому я сделал следующее:
- Удалены пакеты, которые я использовал для установки MPICH (в обоих узлах):
$ sudo apt-get remove libcr-dev mpich mpich-doc
; - Установил OpenMPI (в обоих узлах):
$ sudo apt install openmpi-bin openmpi-doc libopenmpi-dev
;
Установив OpenMPI, мой код заработал. Надеюсь, это поможет любому, кто сталкивается с этой же проблемой!