Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Processes - Metodicka (edited) with MPI - last....doc
Скачиваний:
59
Добавлен:
22.12.2018
Размер:
1.59 Mб
Скачать
      1. Mpi: прием сообщения, размер которого неизвестен заранее.

В данном примере приведена схема работы с сообщением, размер которого заранее неизвестен. Ветвь с номером 0 посылает ветви с номером 1 сообщение, содержащее имя исполняемой программы (т.е. значение нулевого элемента в массиве аргументов командной строки). В ветви с номером 1 вызов MPI_Probe() позволяет получить доступ к описывающей сообщение структуре типа MPI_Status. Затем с помощью вызова MPI_Get_count() можно узнать размер буфера, который необходимо выделить для приема сообщения.

#include <mpi.h>

#include <stdio.h>

int main(int argc, char **argv)

{

int size, rank;

MPI_Init(&argc, &argv); /* Инициализируем библиотеку */

MPI_Comm_size(MPI_COMM_WORLD, &size);

/* Узнаем количество задач в запущенном приложении... */

MPI_Comm_rank (MPI_COMM_WORLD, &rank);

/* ...и свой собственный номер: от 0 до (size-1) */

if ((size > 1) && (rank == 0)) {

/* задача с номером 0 отправляет сообщение*/

MPI_Send(argv[0], strlen(argv[0]), MPI_CHAR, 1, 1, MPI_COMM_WORLD);

printf("Sent to process 1: \"%s\"\n", argv[0]);

} else if ((size > 1) && (rank == 1)) {

/* задача с номером 1 получает сообщение*/

int count;

MPI_Status status;

char *buf;

MPI_Probe(0, 1, MPI_COMM_WORLD, &status);

MPI_Get_count(&status, MPI_CHAR, &count);

buf = (char *) malloc(count * sizeof(char));

MPI_Recv(buf, count, MPI_CHAR, 0, 1, MPI_COMM_WORLD, &status);

printf("Received from process 0: \"%s\"\n", buf);

}

/* Все задачи завершают выполнение */

MPI_Finalize();

return 0;

}

      1. Коммуникации «точка-точка». Неблокирующий режим.

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

Однако, для того, чтобы инициировавшая операцию приема/передачи ветвь имела возможность узнать о том, что операция завершена, необходимо каким-то образом идентифицировать каждую операцию обмена. Для этого в MPI существует механизм так называемых «квитанций» (requests), для описания которых служит тип данных MPI_Request. В момент вызова функции, инициирующей операцию приема/передачи, создается квитанция, соответствующая данной операции, и через параметр-указатель возвращается вызвавшей ветви. Впоследствии, используя эту квитанцию, ветвь может узнать о завершении ранее начатой операции.

Отсылка и прием сообщений в неблокирующем режиме.

Для отсылки и приема сообщений в неблокирующем режиме служат следующие базовые функции:

#include <mpi.h>

int MPI_Isend(void* buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request);

int MPI_Irecv(void* buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Request *request);

Все их параметры, кроме последнего, аналогичны параметрам функций MPI_Send() и MPI_Recv(). Последним параметром служит указатель на переменную типа MPI_Request, которая после возврата из данного вызова будет содержать квитанцию для инициированной операции отсылки или приема данных.

Возврат из функции MPI_Isend() происходит сразу же, как только система инициирует операцию отсылки сообщения, и будет готова начать копировать данные из буфера, переданного в параметре buf. Важно понимать, что возврат из функции MPI_Isend() не означает, что этот буфер можно использовать по другому назначению! Вызвавший процесс не должен производить никаких операций над этим буфером до тех пор, пока не убедится в том, что операция отсылки данных завершена.

Возврат из функции MPI_Irecv() происходит сразу же, как только система инициирует операцию приема данных и будет готова начать принимать данные в буфер, предоставленный в параметре buf, вне зависимости от того, существует ли в этот момент сообщение, удовлетворяющее остальным переданным параметрам (source, tag, comm). При этом вызвавший процесс не может полагать, что в буфере buf находятся принятые данные до тех пор, пока не убедится, что операция приема завершена. Отметим также, что у функции MPI_Irecv() отсутствует параметр status, так как на момент возврата из этой функции информация о принимаемом сообщении, которая должна содержаться в status, может быть еще неизвестна.

В неблокирующем режиме, также как и в блокирующем, доступны различные варианты буферизации при отправке сообщения. Для явного задания режима буферизации, отличного от стандартного, служат следующие функции:

#include <mpi.h>

int MPI_Issend(void* buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request);

int MPI_Ibsend(void* buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request);

int MPI_Irsend(void* buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request);

Отметим, что поскольку MPI_Ibsend() предполагает обязательную буферизацию сообщения, а MPI_rsend() используется лишь тогда, когда на принимающей стороне уже гарантированно инициирован прием сообщения, их использование лишь в некоторых случаях может дать сколь либо заметный выигрыш по сравнению с аналогичными блокирующими вариантами, так как разницу во времени их выполнения составляет лишь время, необходимое для копирования данных.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]