Параллельное программирование: Учебное пособие, страница 100

Отложенный запрос можно сформировать для всех режимов обмена, используя подпрограммы MPI_Bsend_init, MPI_Ssend_init и MPI_Rsend_init. Список параметров у них совпадает со списком параметров подпрограммы MPI_Send_init.

Чтобы инициализировать отложенный обмен, необходимо вызвать подпрограмму MPI_Start:

int MPI_Start(MPI_Request *request)

Входным параметром этой подпрограммы является request — запрос на выполнение операции обмена. Вызов MPI_Start после запроса на обмен, созданным MPI_Send_init, инициирует обмен с теми же свойствами, что и вызов подпрограммы MPI_Isend, а вызов MPI_Start после запроса, созданного MPI_Bsend_init, инициирует обмен аналогичный вызову MPI_Ibsend. Сообщение, которое передано операцией, инициированной с помощью MPI_Start, может быть принято любой подпрограммой приема.

Инициализация всех обменов, чьи запросы на выполнение неблокирующей операции обмена отмечены в массиве requests, осуществляется подпрограммой MPI_Startall:

int MPI_Startall(int count, MPI_Request *requests)

Инициированный отложенный обмен завершается вызовом MPI_Wait, MPI_Test и некоторых других подпрограмм.

5.2.11  Отмена обменов, ожидающих обработки

Аннулировать ожидающие обработки неблокирующие обмены можно с помощью операции MPI_Cancel. Ее можно использовать для освобождения ресурсов, прежде всего памяти, отведенной для размещения буферов:

int MPI_Cancel(MPI_Request *request)

Вызов этой подпрограммы завершается сразу, возможно, еще до реального аннулирования обмена. Аннулируемый обмен следует завершить. Сделать это можно с помощью вызова подпрограмм MPI_Request_free, MPI_WaitMPI_Test  и некоторых других.

Операцию MPI_Cancel можно использовать для аннулирования обменов, использующих как отложенный, так и обычный запрос. После вызова MPI_Cancel и следующего за ним вызова MPI_Wait или MPI_Test запрос на выполнение операции обмена становится неактивным и может быть активизирован для нового обмена. Информация об аннулированной операции содержится в аргументе status.

Подпрограмма MPI_Test_cancelled возвращает значение параметра flag равное true, если обмен, связанный с указанным статусом, успешно аннулирован:

int MPI_Test_cancelled(MPI_Status *status, int *flag)

Аннулирование — трудоемкая операция, не стоит ею злоупотреблять. Запрос на выполнение операции (request) можно аннулировать с помощью подпрограммы MPI_Request_free:

int MPI_Request_free(MPI_Request *request)

При вызове эта подпрограмма помечает запрос на обмен для удаления и присваивает ему значение MPI_REQUEST_NULL. Операции обмена, связанной с этим запросом, дается возможность завершиться, а сам запрос удаляется только после завершения обмена.

Следует учитывать, что после того как запрос аннулирован, нельзя проверить, был ли успешно завершен соответствующий обмен, поэтому активный запрос нельзя аннулировать.

Текст 5.10. Пример c подпрограммой  MPI_Request_free

#include "mpi.h"

#include <stdio.h>

int main(int argc, char *argv[])

{

int rank, tag, cnt, N, status(MPI_STATUS_SIZE);

float sndbuf, rcvbuf;

parameter(bufsize = 4 + MPI_BSEND_OVERHEAD);

byte buff(bufsize);

int cnt = 1;

int tag = 0;

sndbuf = 3.14159;

rcvbuf = 0;

MPI_Init(&argc, &argv);

MPI_Comm_rank(MPI_COMM_WORLD, &myrank);

N = 4;

if (rank == 0)

for(i = 0; i < N; i++)

{

MPI_Isend(&sndbuf, cnt, MPI_FLOAT, 1, tag,

MPI_COMM_WORLD, req);

printf("process %i", rank, " send %i\n", sndbuf);

MPI_Request_free(req);

MPI_Irecv(&rcvbuf, cnt, MPI_FLOAT, 1, tag,

MPI_COMM_WORLD, req);

printf("process %i", rank,

" yet not received %i\n", rcvbuf);

MPI_Wait(req, status);

printf("process %i",rank," received %i\n",rcvbuf);

rcvbuf = 0;

}

else

{

MPI_Irecv(&rcvbuf, cnt, MPI_FLOAT, 0, tag,

MPI_COMM_WORLD, req);

printf("process %i ", rank,

" yet not received %i\n ", rcvbuf);

MPI_Wait(req, status);

printf("process %i ", rank,

" received %i\n ", rcvbuf);

rcvbuf = 0;

for( i=1,i < n – 1,i++)

{