Реферат на тему «Пособие по mpi»
Подготовил Абрамов Андрей А-05-03
26 Ноября 2007 г.
-
MPI_Init(), MPI_Finalize().
Функция MPI_Init() инициализирует параллельные вычисления. В качестве входных параметров используются &argc, &argv из функции main.
MPI_Finalize() завершает выполнение программы MPI.
int MPI_Initialized(int nFlag) показывает, была ли выполнена функция MPI_Init: если nFlag не нуль, то была, иначе – нет.
Далее идет текст программы, иллюстрирующий работу этих функций.
int _tmain(int argc, _TCHAR* argv[])
{
int nRank = 0;
int nInitialized = 0;
int nRes = 0;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &nRank);
printf(" Hello, this is proces number %d\n", nRank);
nRes = MPI_Initialized(&nInitialized);
if(nRes)
{
printf(" MPI_Initialized returned error \n");
}
else
{
if(nInitialized)
{
printf(" MPI was initialized\n");
}
else
{
printf(" MPI was not initialized is \n");
}
}
MPI_Finalize();
return 0;
}
Результат работы данной программы на 3-х процессах:
Hello, this is proces number 1
MPI was initialized
Hello, this is proces number 2
MPI was initialized
Hello, this is proces number 0
MPI was initialized
-
Пример на взаимную блокировку MPI_Send/MPI_Recv.
Функция MPI_Send().
int nError MPI_Send(void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm)
-
buf - начало буфера, содержащего данные, которые будут отосланы. Для C это - адрес.
-
count - число элементов, которые будут отосланы (не байт)
-
datatype - тип данных
-
dest - ранг процесса, места назначения, для сообщения
-
tag - произвольное число, которое можно использовать для отличия от других сообщений
-
comm - (определенный) коммуникатор
-
(nError - возвращаемый функцией код ошибки).
Функция MPI_Send является блокирующей, т.е. управление не вернется программе, пока функция не завершится.
Функция MPI_Recv().
int nError MPI_Recv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status)
Параметры:
-
buf - начало буфера, в котором входящие данные должны быть запомнены. Для C это - адрес.
-
count - число элементов (не байт) в вашем буфере получателя
-
datatype - тип данных
-
source - ранг процесса, от которого данные будут приняты (Он может быть любым при задании параметром MPI_ANY_SOURCE)
-
tag - произвольное число, которое можно использовать для отличия от других сообщений (оно может быть любым при задании параметром MPI_ANY_TAG)
-
comm - (определенный) коммуникатор
-
status - массив или структура возвращаемой информации.
-
(nError - возвращаемый функцией код ошибки).
Пример взаимной блокировки этих двух функций:
Допустим, у нас есть несколько процессов, которые взаимодействуют следующим образом:
Каждый процесс содержит следующий код:
for(i=0; i<n; i++)
{
MPI_Send(…);
}
for(i=0; i<n; i++)
{
MPI_Recv (…);
}
Если запустить эти процессы, мы получим дедлок(тупик), поскольку оба процесса зайдут в функцию MPI_Send() и будут ждать ее завершения. А для ее завершения необходимо выполнение функции MPI_Recv, которая никогда не выполнится.
Следующий способ позволяет избежать дедлока:
Поменяем местами циклы в процессах 2 и 4 (процессы будут располагаться в шахматном порядке):
for(i=0; i<n; i++)
{
MPI_Recv (…);
}
for(i=0; i<n; i++)
{
MPI_Send(…);
}
Таким образом, они будут сначала принимать данные, а потом передавать. В то же время процессы 1,2 будут действовать наоборот. В этом случае дедлока не возникнет.
3) Использование функций MPI_Wait(), MPI_Test(), MPI_Probe().
Функция MPI_Wait – функция ожидания завершения неблокирующей операции. Int nError MPI_Wait(MPI_Request *request, MPI_Status *status) nError – возвращаемый функцией код ошибки. status – информация о завершенной операции. Request – запрос обмена. Это блокирующая операция. Возврат происходит после завершения операции, связанной с запросом request. В параметре status возвращается информация о законченной операции.
MPI_Test - функция проверки завершения неблокирующей операции. Int nError MPI_Test(MPI_Request *request, int *flag, MPI_Status *status) nError – возвращаемый функцией код ошибки. status – атрибуты сообщения, если операция завершилась. Request – запрос обмена. Flag – признак завершенности проверяемой операции. Это неблокирующая операция. Если связанная с запросом request операция завершена, возвращается flag = true, а status содержит информацию о завершенной операции. Если проверяемая операция не завершена, возвращается flag = false, а значение status в этом случае не определено.
int nError MPI_Probe(int source, int tag, MPI_Comm comm, int *flag, MPI_Status *status) source - ранг процесса, от которого данные будут приняты tag - произвольное число, которое можно использовать для отличия от других сообщений comm - (определенный) коммуникатор status - массив или структура возвращаемой информации. flag – удовлетворяет ли сообщение всем требованиям nError - возвращаемый функцией код ошибки.
Операция MPI_PROBE позволяет проверить входные сообщения без их реального приема. Пользователь затем может решить, как ему принимать эти сообщения, основываясь на информации, возвращенной при пробе (преимущественно, на информации, возвращенной аргументом status). В частности, пользователь может выделить память для приемного буфера по величине опробованного сообщения. Функция возвращает flag = true, если имеется сообщение, которое может быть получено и которое соответствует образцу, описанному аргументами source, tag, и comm.
Пример программы, которая использует перечисленные функции. Все процессы, номера которых кратны 2-м рассылают целочисленный буфер процессу с номером на 1 большим, чем у них. Затем проверяем, завершилась ли передача и выводим сообщение. На принимающей стороне проверяем, соответствует ли сообщение заданным параметрам, после этого принимаем. Причем, используем блокирующую операцию MPI_Wait для того, чтобы узнать, что прием закончен и тогда выводим на экран принятые значения с помощью функции mesParam:
// second_test.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "mpi.h"
void mesParam(MPI_Status aStatus)
{
printf("Message parameters: \n");
if(aStatus.cancelled)
{
printf("Cancelled \n");
}
else
{
printf("Not cancelled \n");
}
printf("Error: %d\n", aStatus.MPI_ERROR);
printf("Parameters count: %d\n", aStatus.count);
printf("Source: %d\n", aStatus.MPI_SOURCE);
printf("Tag: \n", aStatus.MPI_TAG);
}