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 Поместите эти узлы за брандмауэр, пожалуйста!

Другие вопросы по тегам