OpenMPI v/s Mvapich2: MPI_Send без MPI_Recv

Я пытаюсь проверить влияние MPI_Send без MPI_Recv, У меня есть следующая программа, которую я компилирую и запускаю, используя openmpi-1.4.5 и mvapich2-1.9. Мне известно, что эти реализации предназначены для двух разных версий стандарта MPI, но я думаю, MPI_Send а также MPI_Recv одинаковы для всех этих стандартов:

#include <mpi.h>
#include <iostream>
#include <assert.h>

using namespace std;

MPI_Comm ping_world;
int mpi_size, mpi_rank;

void* ping(void* args)
{
    int ctr = 0;
    while(1)
    {
            char buff[6] = "PING";
            ++ctr;
            for(int i=0; i<mpi_size; ++i)
            {
                    cout << "[" << ctr << "] Rank " << mpi_rank << " sending " << buff << " to rank " << i << endl;
                    MPI_Send(buff, 6, MPI_CHAR, i, 0, ping_world);
            }
    }
}

int main(int argc, char *argv[])
{
int provided;
MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided);
assert(provided == MPI_THREAD_MULTIPLE);

MPI_Comm_rank (MPI_COMM_WORLD, &mpi_rank);
MPI_Comm_size (MPI_COMM_WORLD, &mpi_size);

    {
            MPI_Group orig_group;
            MPI_Comm_group(MPI_COMM_WORLD, &orig_group);
            int ranks[mpi_size];
            for(int i=0; i<mpi_size; ++i)
                    ranks[i] = i;

            MPI_Group new_group;
            MPI_Group_incl(orig_group, mpi_size, ranks, &new_group);
            MPI_Comm_create(MPI_COMM_WORLD, new_group, &ping_world);
    }

pthread_t th_ping;
pthread_create(&th_ping, NULL, ping, (void *) NULL);

pthread_join(th_ping, NULL);

return 0;
}

С mvapich2 я всегда получаю следующий вывод (не более того). В основном программа, кажется, зависла после 3 строк:

[1] Rank 0 sending PING to rank 0
[1] Rank 1 sending PING to rank 0
[1] Rank 1 sending PING to rank 1

С openmpi я получаю следующий вывод (бесконечный):

[1] Rank 1 sending PING to rank 0
[1] Rank 1 sending PING to rank 1
[1] Rank 0 sending PING to rank 0
[1] Rank 0 sending PING to rank 1
[2] Rank 0 sending PING to rank 0
[2] Rank 0 sending PING to rank 1
[3] Rank 0 sending PING to rank 0
[3] Rank 0 sending PING to rank 1
[4] Rank 0 sending PING to rank 0
[4] Rank 0 sending PING to rank 1
[5] Rank 0 sending PING to rank 0
[2] Rank 1 sending PING to rank 0
[2] Rank 1 sending PING to rank 1
[3] Rank 1 sending PING to rank 0
[3] Rank 1 sending PING to rank 1
[4] Rank 1 sending PING to rank 0
[4] Rank 1 sending PING to rank 1
[5] Rank 1 sending PING to rank 0
[5] Rank 1 sending PING to rank 1
[6] Rank 1 sending PING to rank 0

Вопросы:

  1. Почему такая разница?
  2. Как мне добиться поведения, похожего на openmpi (нескончаемое) при использовании mvapich2?

3 ответа

MPI_Send может возвращаться, когда буфер может безопасно использоваться вызывающей программой. Ничто другое не гарантируется, но есть много различных зависимых от реализации поведений. Разные реализации могут по-разному обрабатывать буферизацию сообщений. Активные протоколы также позволяют транспортировать некоторые короткие (er) сообщения в ранг приема без необходимости публикации соответствующего MPI_Recv.

Если вам нужно, чтобы MPI принудительно принимал сообщение, полученное до возвращения блокирующей отправки, посмотрите на MPI_Ssend.

В реализации MVAPICH2(и MPICH) самоблокирующая отправка блокируется (не буферизируется) до тех пор, пока не будет найден соответствующий MPI_Recv. По этой причине он не зависал на уровне "Ранг 1, отправляющей PING на ранг 0". Это просто выбор реализации.

Это неверная программа MPI для отправки данных без их получения. Проблема, которую вы видите, состоит в том, что ваши посылки не совпадают ни с какими получениями. В зависимости от реализации, MPI_SEND может заблокировать, пока сообщение не будет получено на другом конце. Фактически, все известные мне реализации будут делать это для достаточно больших сообщений (хотя ваше сообщение размером 6 байт, вероятно, нигде не достигает этого порога).

Если вы хотите отправлять сообщения без блокировки, вам необходимо использовать MPI_ISEND, Однако даже для этого нужно в конце концов позвонить MPI_TEST или же MPI_WAIT чтобы быть уверенным, что данные действительно были отправлены, а не просто буферизованы локально.

Я не уверен в специфике того, почему MVAPICH2 зависает, а Open MPI нет, но в конце концов это не имеет значения. Вам нужно изменить свою программу, или вы просто тестируете кейсы, которые в любом случае не должны использоваться.

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