Пособие по MPI (реферат) (2)

2015-08-23СтудИзба

Описание файла

Документ из архива "Пособие по MPI (реферат) (2)", который расположен в категории "". Всё это находится в предмете "параллельные системы и параллельные вычисления" из 9 семестр (1 семестр магистратуры), которые можно найти в файловом архиве НИУ «МЭИ» . Не смотря на прямую связь этого архива с НИУ «МЭИ» , его также можно найти и в других разделах. Архив можно найти в разделе "остальное", в предмете "параллельные системы и параллельные вычисления" в общих файлах.

Онлайн просмотр документа "Пособие по MPI (реферат) (2)"

Текст из документа "Пособие по MPI (реферат) (2)"

Реферат на тему «Пособие по MPI »

Подготовил Абрамов Андрей А-05-03

26 ноября 2007 г.

  1. 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

  1. Пример на взаимную блокировку 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

{

MPI_Send(…);

}

for(i=0; i

{

MPI_Recv (…);

}

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

Следующий способ позволяет избежать дедлока:

Поменяем местами циклы в процессах 2 и 4 (процессы будут располагаться в шахматном порядке):

for(i=0; i

{

MPI_Recv (…);

}

for(i=0; 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);

}

int _tmain(int argc, _TCHAR* argv[])

{

int nRank = 0;

int nSize = 0;

MPI_Init(&argc, &argv);

MPI_Comm_rank(MPI_COMM_WORLD, &nRank);

MPI_Comm_size(MPI_COMM_WORLD, &nSize);

if(nSize % 2 == 0)

{

if(nRank % 2 == 0)

{

int nBuf = 100;

int nRes = 0;

int nTestRes = 0;

int nFlag = 0;

MPI_Request request = MPI_REQUEST_NULL;

MPI_Status* status = MPI_STATUS_IGNORE;

// Асинхронная передача

nRes = MPI_Isend(&nBuf, 1, MPI_INT, nRank + 1, nRank, MPI_COMM_WORLD, &request);

if(nRes)

{

printf("MPI_Isend returned error %d\n", nRes);

}

//----------------------------------------MPI_Test-----------------------------------------

// Проверим, что передача завершилась

nTestRes = MPI_Test(&request, &nFlag, status);

if(nTestRes)

{

printf("MPI_Test returned error %d\n", nTestRes);

}

else

{

if(nFlag)

{

printf("MPI_Isend completed \n");

// Если nFlag==true выведем все параметры сообщения

mesParam(*status);

}

}

}

else

{

int nRes = 0;

int nBuf = 0;

int nFlag = 1;

int nProbeRes = 0;

MPI_Request request;

MPI_Status status;

status.cancelled = 0;

status.count = 1;

status.MPI_ERROR = 0;

status.MPI_SOURCE = nRank;

status.MPI_TAG = nRank;

//----------------------------------------MPI_Probe----------------------------------------

// Проверим, что сообщение удовлетворяет нашим требованиям

nProbeRes = MPI_Probe(nRank - 1, nRank - 1, MPI_COMM_WORLD, &nFlag, &status);

if(nProbeRes)

{

printf("MPI_Probe returned error %d\n", nProbeRes);

}

else

{

if(nFlag)

{

int nWaitResult = 0;

printf("Message matches requirements \n");

// Асинхронный прием

nRes = MPI_Irecv(&nBuf, 1, MPI_INT, nRank - 1, nRank - 1, MPI_COMM_WORLD, &request);

if(nRes)

{

printf("MPI_Irecv returned error %d\n", nRes);

}

//----------------------------------------MPI_Wait-------------------------------------

// Если удовлетворяет, подождем пока закончиться прием данных

nWaitResult = MPI_Wait(&request, &status);

if(nWaitResult)

{

printf("MPI_Wait returned error %d\n", nWaitResult);

}

else

{

// Если прием нормально завершился, выведем параметры сообщения на экран

mesParam(status);

}

}

}

}

}

MPI_Finalize();

return 0;

}

Результат работы программы для 2-х процессов:

Message matches requirements

Message parameters:

Not cancelled

Error: 0

Parameters count: 4

Source: 0

Tag: 0

  1. Функции MPI_Gather, MPI_Scatter

Функция MPI_Gather(). При выполнении этой функции все процессы рассылают данные корневому процессу (включая сам корневой).

int nError MPI_Gather(void* sendbuf, int sendcount,
MPI_Datatype sendtype, void* recvbuf, int recvcount,
MPI_Datatype recvtype, int root, MPI_Comm comm);

sendbuf начальный адрес буфера процесса-отправителя sendcount количество элементов в отсылаемом сообщении (целое) sendtype тип элементов в отсылаемом сообщении recvbuf начальный адрес буфера процесса сборки данных (существенно только для корневого процесса) recvcount количество элементов в принимаемом сообщении (целое, имеет значение только для корневого процесса) recvtype тип данных элементов в буфере процесса-получателя root номер процесса-получателя (целое) comm коммуникатор root – номер корневого процесса nError – возвращаемое значение ошибки.

Пример на функцию MPI_Gather(). Все процессы создают переменную типа int и передают ее корневому (нулевому), который сохраняет их в массив, затем выводит на экран:

int _tmain(int argc, _TCHAR* argv[])

{

int nError = 0;

int nSize = 0;

int nRank = 0;

int* pReadBuf = NULL;

int i=0;

MPI_Init(&argc, &argv);

MPI_Comm_size(MPI_COMM_WORLD, &nSize);

MPI_Comm_rank(MPI_COMM_WORLD, &nRank);

if(nRank == 0)

{

pReadBuf = (int *)malloc(nSize*sizeof(int));

}

nError = MPI_Gather(&nRank, 1, MPI_INT, pReadBuf, 1, MPI_INT, 0, MPI_COMM_WORLD);

if(nRank == 0)

{

printf("Принятые элементы массива: \n");

for(i=0; i

{

printf("%d\n", pReadBuf[i]);

}

}

MPI_Finalize();

return 0;

}

Результат работы функции для 4-х процессов:

Принятые элементы массива:

0

1

2

3

Функция MPI_Scatter(). Эта операция обратна MPI_Gather(), т.е. корневой процесс рассылает данные всем остальным.

int MPI_Scatter(void* sendbuf, int sendcount, MPI_Datatype sendtype,
void* recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm)

sendbuf - начальный адрес буфера процесса-отправителя(используется только корневым процессом) sendcount количество элементов в отсылаемом сообщении (целое, используется только корневым процессом) sendtype тип элементов в отсылаемом сообщении(используется только корневым процессом) recvbuf начальный адрес буфера процесса сборки данных recvcount количество элементов в принимаемом сообщении recvcount - количество элементов recvtype тип данных элементов в буфере процесса-получателя root номер процесса-получателя (целое) root – номер процесса-получателя comm коммуникатор nError – возвращаемое значение ошибки.

Пример использования. Функция создает массив, количество элементов которого равно количеству процессов, затем заполняет массив идущими подряд числами и рассылает их всем процессам:

int _tmain(int argc, _TCHAR* argv[])

{

int nRank = 0;

int nResult = 0;

int* pSendBuf = NULL;

int nRecvBuf = 0;

int nSize = 0;

int i = 0;

MPI_Init(&argc, &argv);

MPI_Comm_rank(MPI_COMM_WORLD, &nRank);

MPI_Comm_size(MPI_COMM_WORLD, &nSize);

pSendBuf = (int *)malloc(nSize*sizeof(int));

for(i = 0; i

{

pSendBuf[i] = i;

}

nResult = MPI_Scatter(pSendBuf, 1, MPI_INT, &nRecvBuf, 1, MPI_INT, 0, MPI_COMM_WORLD);

if(nResult)

{

printf("MPI_Scatter returned error - %d", nResult);

}

else

{

printf("Process rank - %d", nRank);

printf(" nRecvBuf = %d\n", nRecvBuf);

}

MPI_Finalize();

return 0;

}

Результат работы функции для 4- процессов:

Process rank - 2 nRecvBuf = 2

Process rank - 3 nRecvBuf = 3

Process rank - 0 nRecvBuf = 0

Process rank - 1 nRecvBuf = 1

  1. Функции MPI_Reduce MPI_AllReduce

Функция MPI_Reduce

int nError MPI_Reduce(void* operand, void* result, int count, MPI_Datatype datatype, MPI_Op op,  int root, MPI_Comm comm)

operand- операнды функции result- результат, который сохраняется в корневом процессе count-количество ячеек в памяти, на которые ссылаются и операнд и результат datatype – тип данных op – оператор, с помощью которого производятся вычисления root- номер корневого процесса, в котором сохраняются результаты comm. – коммуникатор.

MPI_Reduce() объединяет операнды, сохраненные в *operand, используя оператор op и сохраняет результат в переменной *result корневого процесса root. И операнд, и результат ссылаются на count ячеек памяти с типом datatype. MPI_Reduce() должны вызывать все процессы в коммуникаторе comm. При вызове значения count, datatype и op должны быть одинаковыми в каждом процессе.

Пример использования. Функция суммирует ранги всех процессов и сохраняет их в нулевом:

int _tmain(int argc, _TCHAR* argv[])

{

int nSize = 0;

int nRank = 0;

int nResult = 0;

int nError = 0;

MPI_Init(&argc, &argv);

MPI_Comm_size(MPI_COMM_WORLD, &nSize);

MPI_Comm_rank(MPI_COMM_WORLD, &nRank);

nError = MPI_Reduce(&nRank, &nResult, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);

if(nError)

{

printf("MPI_Reduce returned Error %d\n", nError);

}

else

{

if(!nRank)

{

printf("Result is %d\n", nResult);

}

}

MPI_Finalize();

return 0;

}

Результат работы функции. Вывод полученного значения суммы номеров всех процессов(для 4-х процессов):

Result is 6

Функция MPI_AllReduce() отличается только тем, что сохраняет данные во всех процессах, поэтому в ней не указывается корневой процесс. Список параметров аналогичен предыдущей функции.

int MPI_Allreduce(void* sendbuf, void* recvbuf, int count,

MPI_Datatype datatype, MPI_Op op, MPI_Comm comm)







Свежие статьи
Популярно сейчас
Почему делать на заказ в разы дороже, чем купить готовую учебную работу на СтудИзбе? Наши учебные работы продаются каждый год, тогда как большинство заказов выполняются с нуля. Найдите подходящий учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
5224
Авторов
на СтудИзбе
426
Средний доход
с одного платного файла
Обучение Подробнее