MPI_SEND перестает работать после MPI_BARRIER
Я создаю распределенный веб-сервер в C/MPI, и кажется, что соединение точка-точка полностью перестает работать после первого MPI_BARRIER в моем коде. Стандартный код C работает после барьера, поэтому я знаю, что каждый из потоков проходит через барьер. Двухточечная связь также отлично работает перед барьером. Однако, когда я копирую и вставляю тот же код, который работал со строкой до барьера, в строку после барьера, он перестает работать полностью. ОТПРАВИТЬ будет просто ждать вечно. Когда я пытаюсь использовать вместо этого ISEND, он проходит через линию, но сообщение так и не получено. Я много гуглил эту проблему, и всем, у кого проблемы с MPI_BARRIER, говорят, что барьер работает правильно, а их код неправильный, но я не могу понять, почему мой код неправильный. Что может быть причиной такого поведения?
Вот пример программы, которая демонстрирует это:
#include <mpi.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
int procID;
int val;
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &procID);
MPI_Barrier(MPI_COMM_WORLD);
if (procID == 0)
{
val = 4;
printf("Before send\n");
MPI_Send(&val, 1, MPI_INT, 1, 4, MPI_COMM_WORLD);
printf("after send\n");
}
if (procID == 1)
{
val = 1;
printf("before: val = %d\n", val);
MPI_Recv(&val, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
printf("after: val = %d\n", val);
}
MPI_Finalize();
return 0;
}
Перемещение двух if
операторы перед барьером заставляют эту программу работать правильно.
РЕДАКТИРОВАТЬ - Похоже, что первая связь, независимо от типа, работает, и все будущие связи не удается. Это гораздо более общее, что я думал сначала. Неважно, является ли первое сообщение барьером или каким-либо другим сообщением, никакое будущее сообщение не будет работать должным образом.
1 ответ
Open MPI имеет функцию "знать", когда он использует TCP/IP для связи: он пытается использовать все настроенные сетевые интерфейсы, которые находятся в состоянии "UP". Это представляет проблему, если некоторые другие узлы недоступны через все эти интерфейсы. Это часть жадной оптимизации связи, которую использует Open MPI и иногда, как в вашем случае, приводит к проблемам.
Кажется, что, по крайней мере, второй узел имеет несколько работающих интерфейсов и что этот факт был представлен первому узлу на этапе согласования:
- один настроен с 128.2.100.167
- настроенный с 192.168.109.1 (у вас работает туннель или Xen на машине?)
Барьерное общение происходит по первой сети, а затем по следующей MPI_Send
пытается отправить на второй адрес через вторую сеть, которая, очевидно, не соединяет все узлы.
Самое простое решение - указать Open MPI только использовать nework, соединяющий ваши узлы. Вы можете сказать это, используя следующий параметр MCA:
--mca btl_tcp_if_include 128.2.100.0/24
(или какой бы ни была ваша сеть связи)
Вы также можете указать список сетевых интерфейсов, если он одинаков на всех машинах, например
--mca btl_tcp_if_include eth0
или вы можете указать Open MPI специально исключать определенные интерфейсы (но вы должны всегда указывать ему исключать обратную петлю "lo", если вы делаете это):
--mca btl_tcp_if_exclude lo,virt0
Надеюсь, что это поможет вам и многим другим, у которых, похоже, такие же проблемы, здесь, в SO. Похоже, что в последнее время почти все дистрибутивы Linux начали использовать различные сетевые интерфейсы по умолчанию, что может вызвать проблемы с Open MPI.
PS Поместите эти узлы за брандмауэр, пожалуйста!