10
MPI_TAG и MPI_ERROR. Реальные значения номера процесса-отправителя,
идентификатора сообщения и код ошибки доступны через status.MPI_SOURCE, status.
MPI_TAG и status.MPI_ERROR. В языке Fortran параметр status является целочисленным
массивом размера MPI_STATUS_SIZE. Константы MPI_SOURCE, MPI_TAG и
MPI_ERROR являются индексами по данному массиву для доступа к значениям
соответствующих полей, например, status(MPI_SOURCE).
Имеет место некоторая несимметричность операций посылки и приема сообщений. С
помощью константы MPI_ANY_SOURCE можно принять сообщение от любого процесса.
Однако в случае посылки данных требуется явно указать номер принимающего процесса.
В стандарте оговорено, что если один процесс последовательно посылает два
сообщения другому процессу, и оба эти сообщения соответствуют одному и тому же вызову
MPI_Recv, то первым будет принято сообщение, которое было отправлено раньше. Вместе с
тем, если два сообщения были одновременно отправлены разными процессами и оба
сообщения соответствуют одному и тому же вызову MPI_Recv, то порядок их получения
принимающим процессом заранее не определен.
MPI не гарантирует выполнения свойства "справедливости" при распределении
приходящих сообщений. Предположим, что процесс Р1 послал сообщение, которое может
быть принято процессом Р2. Однако прием может не произойти, в принципе, сколь угодно
долгое время. Такое возможно, например, если процесс Р3, постоянно посылает сообщения
процессу Р2, также подходящие под шаблон MPI_Recv.
Последнее замечание относительно использования блокирующих функций приема и
посылки связано с возможным возникновением тупиковой ситуации. Предположим, что
работают два параллельных процесса и они хотят обменяться данными. Было бы вполне
естественно в каждом процессе сначала воспользоваться функцией MPI_Send, а затем
MPI_Recv. Но именно этого и не стоит делать. Дело в том, что заранее неизвестно, как
реализована функция MPI_Send. Если разработчики для гарантии корректного повторного
использования буфера посылки заложили схему, при которой посылающий процесс ждет
начала приема, то возникнет классический тупик. Первый процесс не может вернуться из
функции посылки, поскольку второй не начинает прием сообщения. А второй процесс не
может начать прием сообщения, поскольку сам по похожей причине застрял на посылке.
Выход из этой ситуации прост. Нужно использовать либо неблокирующие функции
приема/передачи, либо функцию совмещенной передачи и приема.
Для определения размера области памяти, выделяемой для хранения сообщения,
используется функция MPI_Probe. Ее прототип:
int MPI_Probe(int source, int msgtag, MPI_Соmm соmm, MPI Status *status)
Здесь:
source - номер процесса-отправителя или MPI_ANY_SOORCE;
msgtag - идентификатор ожидаемого сообщения или MPI_ANY_TAG;
comm - идентификатор коммуникатора;
OUT status - параметры найденного подходящего сообщения.
Возврата из функции не произойдет до тех пор, пока сообщение с подходящим
идентификатором и номером процесса-отправителя, не будет доступно для получения.
Атрибуты доступного сообщения можно определить обычным образом с помощью
параметра status. Функция определяет только факт прихода сообщения, но реально его не
принимает.
Прием/передача сообщений без блокировки.
В отличие от функций с блокировкой, возврат из функций данной группы происходит
сразу без какой либо блокировки процессов. На фоне дальнейшего выполнения программы
одновременно происходит и обработка асинхронно запущенной операции. В принципе,
данная возможность исключительно полезна для создания эффективных программ. В самом
деле, программист знает, что в некоторый момент ему потребуется массив, который
вычисляет другой процесс. Он заранее выставляет в программе асинхронный запрос на