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

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

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

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

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

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

Московский Энергетический Институт

(Технический Университет)

Кафедра Прикладной Математики

Реферат

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

Выполнил: Ясенков Е.М.

Группа: А-13-03

Москва 2007

1. MPI_Init, MPI_Finalize, “Hello, World” с анализом результата MPI_Init

Функция MPI_Init() применяется для инициализации среды выполнения MPI-программы. Параметрами функции являются количество аргументов в командной строке и адрес указателя на массив символов текста самой командной строки.

Функция MPI_Finalize() применяется для завершения выполнения MPI-программы.

Как результат, можно отметить, что структура параллельной программы, разработанная с использованием MPI, должна иметь следующий вид:

#include "mpi.h"

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

{

// программный код без использования функций MPI

MPI_Init(&argc, &argv);

// программный код с использованием функций MPI

MPI_Finalize();

// программный код без использования функций MPI

return 0;

}

Все функции MPI (кроме MPI_Wtime и MPI_Wtick) возвращают в качестве своего значения код завершения. При успешном выполнении функции возвращаемый код равен MPI_SUCCESS. Другие значения кода завершения свидетельствуют об обнаружении тех или иных ошибочных ситуаций в ходе выполнения функций. Для выяснения типа обнаруженной ошибки используются предопределенные именованные константы, среди которых:

MPI_ERR_BUFFER — неправильный указатель на буфер;

MPI_ERR_TRUNCATE — сообщение превышает размер приемного буфера;

MPI_ERR_COMM — неправильный коммуникатор;

MPI_ERR_RANK — неправильный ранг процесса и др.

Далее следует пример программы “Hello, World” с анализом результата MPI_Init():

#include "mpi.h"

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

{

int ProcRank, Error;

Error = MPI_Init(&argc, &argv);

MPI_Comm_rank(MPI_COMM_WORLD, &ProcRank);

printf("Hello, World! from process %2d... ", ProcRank);

if (Error == MPI_SUCCESS)

printf("Ошибок нет\n");

else if (Error == MPI_ERR_RANK)

printf("Ошибка - неправильный ранг процесса");

else if (Error == MPI_ERR_UNKNOWN)

printf("Неизвестная ошибка");

MPI_Finalize();

return 0;

}

Результат выполнения программы на 5 процессах:

Hello, World! from process 2... Ошибок нет

Hello, World! from process 3... Ошибок нет

Hello, World! from process 4... Ошибок нет

Hello, World! from process 0... Ошибок нет

Hello, World! from process 1... Ошибок нет

---------------------------------------------------------------------------

2. MPI_Send, MPI_Recv, анализ структуры MPI_Status

Функция MPI_Send применяется для передачи сообщения:

int MPI_Send(void *buf, int count, MPI_Datatype type, int dest, int tag, MPI_Comm comm), где

  • buf — адрес буфера памяти, в котором располагаются данные отправляемого сообщения;

  • count — количество элементов данных в сообщении;

  • type — тип элементов данных пересылаемого сообщения;

  • dest — ранг процесса, которому отправляется сообщение;

  • tag — значение-тег, используемое для идентификации сообщения;

  • comm — коммуникатор, в рамках которого выполняется передача данных.

Функция MPI_Recv применяется для получения сообщения:

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 – указатель на структуру данных с информацией о результате выполнения операции приема данных.

Структура MPI_Status (взято из файла mpi.h):

typedef struct MPI_Status {

int count; // необязательное поле - количество элементов данных в сообщении

int cancelled; // необязательное поле

int MPI_SOURCE; // ранг процесса–отправителя принятого сообщения;

int MPI_TAG; // тэг принятого сообщения

int MPI_ERROR; // код ошибки

} MPI_Status;

В следующем примере процесс 0 посылает сообщение из 12 символов процессу 1 и тот также в ответ шлет сообщение процессу 0:

# include "mpi.h"

# include

int main(int argc, char** argv)

{

int numtasks, rank, rc, dest, source, tag = 1;

char* outmsg1 = "Hello first\0";

char* outmsg2 = "Hello zero\0";

char inmsg[12];

MPI_Status stat;

MPI_Init(&argc, &argv);

MPI_Comm_size(MPI_COMM_WORLD, &numtasks);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

if(rank == 0){

dest = 1;

source = 1;

rc = MPI_Send(outmsg1, 12, MPI_CHAR, dest, tag, MPI_COMM_WORLD);

rc = MPI_Recv(inmsg, 12, MPI_CHAR, source, tag, MPI_COMM_WORLD, &stat);

printf("Process %d received message: \"%s\"\n", rank, inmsg);

}

else if(rank == 1){

dest = 0;

source = 0;

rc = MPI_Send(outmsg2, 12, MPI_CHAR, dest, tag, MPI_COMM_WORLD);

rc = MPI_Recv(inmsg, 12, MPI_CHAR, source, tag, MPI_COMM_WORLD, &stat);

printf("Process %d received message: \"%s\"\n", rank, inmsg);

}

MPI_Finalize();

return 0;

}

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

Process 1 received message: "Hello first"

Process 0 received message: "Hello zero"

-----------------------------------------------------------------------------------------------------------------

3. Разрешение взаимной блокировки Send/Recv с помощью функции MPI_Sendrecv

Пример взаимной блокировки этих двух функций:

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

Каждый процесс содержит следующий код:

for(i=0; i

{

MPI_Send(…);

}

for(i=0; i

{

MPI_Recv(…);

}

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

Чтобы избежать взаимной блокировки можно выполнить взаимный обмен данными между процессами, используя совмещенную операцию MPI_Sendrecv.

int MPI_Sendrecv(void *sbuf, int scount, MPI_Datatype stype, int dest, int stag, void *rbuf, int count, MPI_Datatype rtype, int source, int rtag, MPI_Comm comm, MPI_Status *status), где

  • sbuf, scount, stype, dest, stag — параметры передаваемого сообщения;

  • rbuf, rcount, rtype, source, rtag — параметры принимаемого сообщения;

  • comm — коммуникатор, в рамках которого выполняется передача данных;

  • status — структура данных с информацией о результате выполнения операции.

Тогда каждый процесс будет содержать следующий код:

for(i=0; i

{

MPI_Sendrecv(…);

}

------------------------------------------------------------------------

4. Пример использования MPI_Waitall, MPI_Waitany

Процедура MPI_Waitall:

int MPI_Waitall(int count, MPI_Request *requests, MPI_Status *statuses), где

–      count - число идентификаторов;

–      requests - массив идентификаторов асинхронного приема или передачи;

–      OUT statuses - параметры сообщений.

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

Пример. Сеть из 4 узлов с круговой топологией. Каждый узел посылает двум соседям сообщения и ждет ответа от них. Работа каждого узла не завершится до тех пор, пока все 4 операции не будут выполнены.

# include

# include

int main(int argc, char** argv)

{

int numtasks, rank, next, prev, buf[2], tag1 = 1, tag2 = 2;

MPI_Request reqs[4];

MPI_Status stats[4];

MPI_Init(&argc,&argv);

MPI_Comm_size(MPI_COMM_WORLD, &numtasks);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

prev = rank - 1;

next = rank + 1;

if (rank == 0) prev = numtasks - 1;

if (rank == (numtasks - 1)) next = 0;

MPI_Irecv(&buf[0], 1, MPI_INT, prev, tag1, MPI_COMM_WORLD, &reqs[0]);

MPI_Irecv(&buf[1], 1, MPI_INT, next, tag2, MPI_COMM_WORLD, &reqs[1]);

MPI_Isend(&rank, 1, MPI_INT, prev, tag2, MPI_COMM_WORLD, &reqs[2]);

MPI_Isend(&rank, 1, MPI_INT, next, tag1, MPI_COMM_WORLD, &reqs[3]);

MPI_Waitall(4, reqs, stats);

printf("Node %d: all ok!\n", rank);

MPI_Finalize();

}

Результат выполнения программы на 4 процессах:

Node 1: all ok!

Node 3: all ok!

Node 2: all ok!

Node 0: all ok!

Процедура MPI_Waitany:

int MPI_Waitany(int count, MPI_Request *requests, int *index, MPI_Status *status), где

–      count - число идентификаторов;

–      requests - массив идентификаторов асинхронного приема или передачи;

–      OUT index - номер завершенной операции обмена;

–      OUT status - параметры сообщений.

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

Пример. Изменим предыдущий пример используя функцию MPI_Waitany вместо MPI_Waitall.

# include

# include

int main(int argc, char** argv)

{

int numtasks, rank, next, prev, buf[2], tag1 = 1, tag2 = 2;

int *i;

MPI_Request reqs[4];

MPI_Status stats[4];

MPI_Init(&argc,&argv);

MPI_Comm_size(MPI_COMM_WORLD, &numtasks);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

prev = rank - 1;

next = rank + 1;

if (rank == 0) prev = numtasks - 1;

if (rank == (numtasks - 1)) next = 0;

MPI_Irecv(&buf[0], 1, MPI_INT, prev, tag1, MPI_COMM_WORLD, &reqs[0]);

MPI_Irecv(&buf[1], 1, MPI_INT, next, tag2, MPI_COMM_WORLD, &reqs[1]);

MPI_Isend(&rank, 1, MPI_INT, prev, tag2, MPI_COMM_WORLD, &reqs[2]);

MPI_Isend(&rank, 1, MPI_INT, next, tag1, MPI_COMM_WORLD, &reqs[3]);

MPI_Waitany(4, reqs, &i, stats);

printf("Node %d: all ok!\n", rank);

MPI_Finalize();

}

Результат выполнения программы на 4 процессах:

Node 1: all ok!

Node 3: all ok!

Node 2: all ok!

Node 0: all ok!

--------------------------------------------------

5. Пример использования MPI_Bcast

Broadcast - передача сообщения от одного процесса ко всем остальным процессам группы, включая его самого. Схематически broadcast можно изобразить следующим образом:



int MPI_Bcast(void *buff, int count, MPI_Datatype datatype, int root, MPI_Comm comm), где

  • buff - адрес начала буфера, хранящего передаваемое сообщение

  • count - количество передаваемых элементов

  • datatype - тип передаваемых элементов

  • root - номер корневого процесса, т.е. номер процесса от которого будет передаваться сообщение всем остальным процессам

  • comm - идентификатор группы

Пример. Каждый не root процесс в буфере sbuf хранит строку "I am not root", а root-процесс кладет себе в буфер sbuf строку "Hello from root" и рассылает ее при помощи MPI_Bcast всем остальным. В результате, у каждого не root процесса в буфере оказывается именно это сообщение.

# include

# include

# include

int main(int argc, char** argv)

{

int numtasks, rank, root;

char sbuf[20];

strcpy(sbuf, "I am not root\0");

root = 1;

MPI_Init(&argc,&argv);

MPI_Comm_size(MPI_COMM_WORLD, &numtasks);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

if(rank == root) strcpy(sbuf, "Hello from root\0");

MPI_Bcast(sbuf, 16, MPI_CHAR, root, MPI_COMM_WORLD);

if(rank == root) strcpy(sbuf, "I am root\0");

printf("I am %d. Message received: %s\n", rank, sbuf);

MPI_Finalize();

return 0;

}

Результат выполнения программы на 5 процессах:

I am 0. Message received: Hello from root

I am 3. Message received: Hello from root

I am 4. Message received: Hello from root

I am 1. Message received: I am root

I am 2. Message received: Hello from root

--------------------------------------------------------------------------

6. Пример использования MPI_Gatherv и MPI_Scatterv

Функция MPI_Gatherv:

int MPI_Gatherv (void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int *recvcnts, int *displs, MPI_Datatype recvtype, int root, MPI_Comm comm), где

  • sendbuf - Адрес, по которому находятся отправляемые данные

  • sendcount - Число отправляемых данных (в каждом процессе — свое)

  • sendtype - Тип отправляемых данных

  • recvcounts - Целочисленный массив размера, равного числу процессов в коммуникаторе; каждый элемент этого массива содержит число элементов, принимаемых от процесса с рангом, равным номеру этого элемента.

  • displs - Целочисленный массив размера, равного числу процессов в коммуникаторе. i-тый элемент определяет смещение (в элементах) относительно адреса recvbuf, по которому разместить данные, приходящие от процесса с рангом i. (имеет значение только в процессе с рангом root)

  • recvtype - Тип принимаемых данных (имеет значение только в процессе с рангом root)

  • root - ранг процесса, который принимает данные.

  • comm - communicator (handle)

  • OUT recvbuf - Адрес, по которому принимаются данные. (имеет значение только в процессе с рангом root)

Пример. Здесь каждый процесс посылает 100 чисел типа int корневому процессу, но каждое множество (100 элементов) размещается с некоторым шагом (stride) относительно конца размещения предыдущего множества. Чтобы получить этот эффект нужно использовать MPI_GATHERV и аргумент displs. Полагаем, что stride > 100.

MPI_Comm comm;

int gsize,sendarray[100];

int root, *rbuf, stride;

int *displs,i,*rcounts;

...

MPI_Comm_size(comm, &gsize);

rbuf = (int *)malloc(gsize*stride*sizeof(int));

displs = (int *)malloc(gsize*sizeof(int));

rcounts = (int *)malloc(gsize*sizeof(int));

for (i=0; i

displs[i] = i*stride;

rcounts[i] = 100;

}

MPI_Gatherv(sendarray, 100, MPI_INT, rbuf, rcounts, displs,

MPI_INT, root, comm);

Функция MPI_Scatterv:

MPI_SCATTERV(sendbuf, sendcounts, displs, sendtype, recvbuf, recvcount, ecvtype,
root, comm)

IN

sendbuf

адрес буфера посылки (альтернатива, используется только корневым процессом)

IN

sendcounts

целочисленный массив (размера группы), определяющий число элементов, для отправки каждому процессу

IN

displs

целочисленный массив (размера группы). Элемент i указывает смещение (относительно sendbuf, из которого берутся данные для процесса take the i)

IN

sendtype

тип элементов посылающего буфера (дескриптор)

OUT

recvbuf

адрес принимающего буфера (альтернатива)

IN

recvcount

число элементов в посылающем буфере (целое)

IN

recvtype

тип данных элементов принимающего буфера (дескриптор)

IN

root

номер посылающего процесса (целое)

IN

comm

коммуникатор (дескриптор)

Пример. Корневой процесс рассылает множества из 100 чисел типа int остальным процессам, но множества размещены в посылающем буфере с шагом stride, поэтому нужно использовать MPI_Scatterv. Полагаем stride > 100.

MPI_Comm comm;

int gsize,*sendbuf;

int root, rbuf[100], i, *displs, *scounts;

...

MPI_Comm_size(comm, &gsize);

sendbuf = (int*)malloc(gsize*stride*sizeof(int));

...

displs = (int*)malloc(gsize*sizeof(int));

scounts = (int*)malloc(gsize*sizeof(int));

for (i=0; i

displs[i] = i*stride;

scounts[i] = 100;

}

MPI_Scatterv(sendbuf, scounts, displs, MPI_INT, rbuf, 100,

MPI_INT, root, comm);

9


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