Наиболее часто используемыми блокирующими функциями передачи данных типа “точка-точка”(peer-to-peer) являются функции MPI_Send и MPI_Recv.
Для передачи сообщения процесс-отправитель выполняет функцию:
int MPI_Send (void *buf, int count, MPI_Datatype type, int dest, int tag, MPI_Comm comm),
где
- buf – адрес буфера памяти, в котором располагаются данные отправляемого сообщения,
- count – количество элементов данных в сообщении,
- type - тип элементов данных пересылаемого сообщения,
- dest - ранг процесса, которому отправляется сообщение,
- tag - значение-тег, используемое для идентификации сообщений(
Arbitrary non-negative integer assigned by the programmer to uniquely identify a message. Send and receive operations should match message tags. For a receive operation, the wild card MPI_ANY_TAG can be used to receive any message regardless of its tag. The MPI standard guarantees that integers 0-32767 can be used as tags, but most implementations allow a much larger range than this.)
- comm - коммуникатор, в рамках которого выполняется передача данных.
Для указания типа пересылаемых данных в MPI имеется ряд базовых типов, полный список которых приведен в табл. 3.4.4.1. 1.
Таблица 3.4.4.1.1. Базовые (пpедопpеделенные) типы данных MPI для языка C
Следует отметить:
1. Отправляемое сообщение определяется через указание блока памяти (буфера), в котором это сообщение располагается. Используемая для указания буфера триада
(buf, count, type)
входит в состав параметров практически всех функций передачи данных,
2. Процессы, между которыми выполняется передача данных, в обязательном порядке должны принадлежать коммуникатору, указываемому в функции MPI_Send,
3. Параметр tag используется только при необходимости различения передаваемых сообщений, в противном случае в качестве значения параметра может быть использовано произвольное целое число (см. также описание функции MPI_Recv).
Сразу же после завершения функции MPI_Send процесс-отправитель может начать повторно использовать буфер памяти, в котором располагалось отправляемое сообщение. Вместе с этим, следует понимать, что в момент завершения функции MPI_Send состояние самого пересылаемого сообщения может быть совершенно различным - сообщение может располагаться в процессе-отправителе, может находиться в процессе передачи, может храниться в процессе-получателе или же может быть принято процессом-получателем при помощи функции MPI_Recv. Тем самым, завершение функции MPI_Send означает лишь, что операция передачи начала выполняться и пересылка сообщения будет рано или поздно будет выполнена
Для приема сообщения процесс-получатель должен выполнить функцию:
int MPI_Recv(void *buf, int count, MPI_Datatype type, int source,int tag, MPI_Comm comm, MPI_Status *status)
,где
- buf, count, type – буфер памяти для приема сообщения, назначение каждого отдельного параметра соответствует описанию в MPI_Send,
- source - ранг процесса, от которого должен быть выполнен прием сообщения,
- tag - тег сообщения, которое должно быть принято для процесса,
- comm - коммуникатор, в рамках которого выполняется передача данных,
- status – указатель на структуру данных с информацией о результате выполнения операции приема данных.
Следует отметить:
1. Буфер памяти должен быть достаточным для приема сообщения, а тип элементов передаваемого и принимаемого сообщения должны совпадать; при нехватке памяти часть сообщения будет потеряна и в коде завершения функции будет зафиксирована ошибка переполнения,
2. При необходимости приема сообщения от любого процесса-отправителя для параметра source может быть указано значение MPI_ANY_SOURCE,
3. При необходимости приема сообщения с любым тегом для параметра tag может быть указано значение MPI_ANY_TAG,
4. Параметр status позволяет определить ряд характеристик принятого сообщения:
- status.MPI_SOURCE – ранг процесса-отправителя принятого сообщения,
- status.MPI_TAG - тег принятого сообщения.
Функция, которая возвращает в переменной count количество элементов типа type в принятом сообщении.
MPI_Get_count(MPI_Status *status, MPI_Datatype type, int *count)
Вызов функции MPI_Recv не должен согласовываться со временем вызова соответствующей функции передачи сообщения MPI_Send – прием сообщения может быть инициирован до момента, в момент или после момента начала отправки сообщения.
По завершении функции MPI_Recv в заданном буфере памяти будет располагаться принятое сообщение. Принципиальный момент здесь состоит в том, что функция MPI_Recv является блокирующей для процесса-получателя, т.е. его выполнение приостанавливается до завершения работы функции. Таким образом, если ожидаемое для приема сообщение будет отсутствовать, выполнение параллельной программы будет блокировано.