Я пытаюсь проверить влияние 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
Вопросы:
MPI_Send может возвращаться, когда буфер может безопасно использоваться вызывающей программой. Ничто другое не гарантируется, но есть много различных зависимых от реализации поведений. Различные реализации могут по-разному обрабатывать буферизацию сообщений. Активные протоколы также позволяют транспортировать некоторые короткие (er) сообщения в ранг приема без необходимости публикации соответствующего MPI_Recv.
Если вам нужно, чтобы MPI принудительно принимал сообщение, полученное до возвращения блокирующей отправки, посмотрите на MPI_Ssend.
Это неверная программа MPI для отправки данных без их получения. Проблема, которую вы видите, состоит в том, что ваши посылки не совпадают ни с какими получениями. В зависимости от реализации, MPI_SEND
может блокироваться, пока сообщение не будет получено на другом конце. Фактически, все известные мне реализации будут делать это для достаточно больших сообщений (хотя ваше сообщение размером 6 байт, вероятно, нигде не достигает этого порога).
Если вы хотите отправлять сообщения без блокировки, вам необходимо использовать MPI_ISEND
, Однако даже для этого нужно в конце концов позвонить MPI_TEST
или же MPI_WAIT
чтобы быть уверенным, что данные действительно были отправлены, а не просто помещены в буфер.
Я не уверен в специфике того, почему MVAPICH2 зависает, а Open MPI нет, но в конце концов это не имеет значения. Вам нужно изменить свою программу, или вы просто тестируете кейсы, которые в любом случае не должны использоваться.
В реализации MVAPICH2 (и MPICH) самоблокирующая отправка блокируется (не буферизируется) до тех пор, пока не будет найден соответствующий MPI_Recv. По этой причине он не зависал на уровне «Ранг 1, отправляющей PING на ранг 0». Это просто выбор реализации.