Я ответил вам в списке пользователей Open MPI, но также опубликую его здесь, на случай, если кто-то еще сочтет это полезным. Я полагаю, что Джефф Сквайрс уже ответил на ваш вопрос в списке рассылки Open MPI или, по крайней мере, намекнул на возможную проблему. Сообщения MPI принимаются в том порядке, в котором они были отправлены, но только в пределах определенного кортежа (тег, коммуникатор). В основном это означает:
- внутри одного коммуникатора вы можете получать сообщения не по порядку, если они имеют разные теги;
- сообщения с одним и тем же тегом могут быть получены не по порядку, если они были переданы в разных контекстах (коммуникаторах).
Но вот в чем загвоздка: вы не можете получить сообщение, если операция отправки еще не была отправлена. Если у вас есть две последовательные операции отправки, вы должны убедиться, что первая не будет заблокирована навсегда. Стандартная операция отправки MPI MPI_Send
может быть реализована различными способами (в стандарте не указано, как именно), но в большинстве реализаций MPI она ведет себя как буферизованная отправка для очень маленьких сообщений и как синхронная отправка для больших сообщений. Если у вас есть следующие два вызова в вашем процессе отправителя:
MPI_Send(largedata, largecount, MPI_INT, dest, tag1, MPI_COMM_WORLD);
MPI_Send(smalldata, smallcount, MPI_INT, dest, tag2, MPI_COMM_WORLD);
может случиться так, что первый MPI_Send
на самом деле будет вести себя как синхронный, т. е. он не вернется, если соответствующая операция приема не будет отправлена на стороне получателя. Предположим, что ваш код получателя:
MPI_Probe(src, tag2, MPI_COMM_WORLD, &status);
MPI_Recv(largedata, largecount, MPI_INT, src, tag1, MPI_COMM_WORLD, &status);
Это, скорее всего, приведет к тупику, потому что MPI_Probe
является блокирующим вызовом, т. е. он не вернется, пока не будет отправлена совпадающая отправка, т. е. должен будет выполниться второй MPI_Send
, что произойдет только после возврата первой отправки, но это не произойдет, если MPI_Recv
в приемнике выполняется... Я думаю, вы поняли идею
Чтобы предотвратить взаимоблокировку, вы можете изменить код отправителя, чтобы использовать неблокирующую отправку:
MPI_Request req;
MPI_Isend(largedata, largecount, MPI_INT, dest, tag1, MPI_COMM_WORLD, &req);
MPI_Send(smalldata, smallcount, MPI_INT, dest, tag2, MPI_COMM_WORLD);
MPI_Wait(&req, MPI_STATUS_IGNORE);
При использовании неблокирующей операции вызов отправки возвращается немедленно, и операция продолжается в фоновом режиме, поэтому вторая отправка будет выполнена сразу после этого. Теперь будет два ожидающих сообщения, и они могут быть получены в любом порядке, поскольку они несут разные теги.
person
Hristo Iliev
schedule
01.10.2012