В парах MPI_Send/MPI_Recv могут ли данные быть потеряны, если они не синхронизированы правильно?

Позволь мне объяснить. Рассмотрим 4 подчиненных узла 1, 2, 3, 4 и главный узел 0. Теперь 1, 2, 3, 4 необходимо отправить данные на 0. 0 получает эти данные в следующем формате.

for(int proc = 1;proc<procCount;proc++) // for each processor cpu (procCount = 5)
{
    for(int p = 0;p<50;p++)
    {

    std::cout<<proc<<"\tA\t"<<p<<std::endl;

    // read in binary datas
   int chunkP;
   int realP;
   real fitnessVal;
   real fitnessValB;
   real fitnessValC;
   int conCount;
   real subConCount;
   real networkEnergyLoss;
   real movementEnergyLoss;
   long spikeCount;

   MPI_Recv (reinterpret_cast < char *>(&chunkP),
      sizeof (chunkP),
                     MPI_CHAR,proc,MPI_ANY_TAG,MPI_COMM_WORLD,&stat);
   MPI_Recv (reinterpret_cast < char *>(&realP),
      sizeof (realP),
                        .
                        .
                        .
           }
     }

Ясно, что порядок, в котором 1, 2, 3 и 4 отправляют данные в 0, нельзя предположить (поскольку все они работают независимо друг от друга — 2 может отправлять данные раньше 1). Таким образом, если предположить, что 2 отправляет свои данные до 1 (например), цикл приема в 0, показанный выше, не будет инициирован до тех пор, пока исходный тег «proc» в команде MPI_Recv не будет сопоставлен с процессором «1», потому что внешний цикл for принудительно этот заказ.

Итак, что происходит, так это то, что цикл «ждет», пока не поступят данные из 1, прежде чем он сможет сделать что-либо еще, даже если уже есть данные, поступающие из 2, 3 и 4. Что происходит с этими данными, поступающими из 2, 3 и 4, если они прибывает до 1? Можно ли его «забыть» в том смысле, что как только данные из «1» начинают поступать, а затем proc увеличивается до 2, данные, которые он изначально пытался получить из 2, просто больше не существуют? Если его «забыть», вся распределенная симуляция просто зависнет, потому что она никогда не сможет правильно обрабатывать данные конкретного ведомого процесса.

Спасибо, Бен.


person Ben J    schedule 24.11.2010    source источник


Ответы (1)


Во-первых, вы действительно хотите получить MPI_CHAR в chunkP - int - разве вы не должны получить MPI_INT?

Сообщения с рангом 1:4 не потеряются — они будут поставлены в очередь до тех пор, пока ранг 0 не решит их получить. Такое поведение предписано стандартом MPI.

Если сообщения достаточно велики, ранги 1:4 могут блокироваться до тех пор, пока они не смогут фактически отправить свои сообщения на ранг 0 (большинство реализаций MPI имеют ограниченную буферизацию).

Вы также можете рассмотреть возможность того, чтобы ранг 0 выполнял MPI_ANY_SOURCE получение для первого получения, чтобы увидеть, кто готов отправить. Однако вам нужно позаботиться о том, чтобы последующие получения были отправлены для соответствующего источника — посмотрите в структуре MPI_Status, чтобы увидеть, откуда на самом деле было отправлено сообщение.

person Edric    schedule 24.11.2010
comment
На самом деле, что касается вашего первого комментария, нет, я не обязательно имею в виду MPI_INT. Поскольку у меня есть так много разных типов данных, которые нужно получить (включая числа с плавающей запятой, целые числа, логические значения и т. д.), я предпочитаю получать их все как MPI_CHAR, а затем переинтерпретировать их в требуемые типы данных. Вы видите какие-либо проблемы с этим методом?... Спасибо также за другие ваши комментарии, я обязательно рассмотрю предложение MPI_ANY_SOURCE. - person Ben J; 24.11.2010
comment
А, понятно - в таком случае получение MPI_CHAR (или даже MPI_BYTE) нормально. - person Edric; 24.11.2010