Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
VVS_ex_fin.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
8.24 Mб
Скачать
  1. Стандарт mpi. Идентификация в mpi. Цели разработчиков mpi. Классификация функций mpi. Структура mpi-программы. Пример программы.

Стандарт MPI.

MPI – Message Passing Interface – интерфейс приема сообщений.

MPI – стандарт на программный инструментарий для обеспечения связей между ветвями параллельной программы. Стандарт MPI определяет синтаксис, семантику библиотечных функций, используемых при написании параллельных программ с передачей сообщений на языках Fortran, C, C++. MPI предоставляет единый механизм взаимодействия ветвей параллельной программы, независимо от машинной архитектуры, расположения ветвей по процессорам и API операционных систем. MPI поддерживает архитектуры: одно- и многопроцессорные. С общей и распределенной памятью. Программы, использующие MPI, легче отлаживаются и быстрее переносятся на другие платформы, в идеале просто перекомпиляцией.

Идентификация в MPI

Три типа идентификаторов:

1)Идентификаторов типов данных. Пример: MPI_Status

2)Определенные константы. Эти константы, которые могут вводиться в виде имени. В разных версиях MPI могут быть разные числа. Идентификаторы переопределенных констант всегда пишутся с заглавной буквы. Пример:

MPI_COMM_WORLD, MPI_INIT

3)Идентификаторы функций библиотеки. Строятся по двум шаблонам:

- MPI_<имя категории функции>_<имя операции>(MPI_Comm_size)

- MPI_<имя операции> (MPI_Send)

<имя категории функции> - первая буквы заглавная, остальные маленькие

<имя операции> - всегда маленькими

Цели MPI (разработка)

  1. Разработать программный интерфейс параллельного программирования

  2. Достичь эффективности коммуникаций

  3. Возможность выполнять параллельные программы в разнородной среде.

  4. Использование стилей Fortran и C интерфейса

  5. Достижение надежности коммуникаций

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

  7. Определить интерфейс, который можно было бы реализовать на многих существующих системах.

Классификация функций MPI

1)Локальность:

- локальные - вызываются и действуют только в рамках одного вызывающего их процесса

(MPI_Comm_size, MPI_Comm_rank)

- не локальные - по своему действию связаны с функциями других процессов (MPI_Send)

- общие – для выполнения своей задачи должны быть вызваны всеми процессам программы или области связи (MPI_init, MPI_Finalize, MPI_Barrier)

2) Синхронизация:

- синхронные

- асинхронные

3) Блокировка:

- блокирующие (приостанавливают на время выполнения своей работы вызывающий их процесс)

- не блокирующие (возвращает управление процессу сразу после их вызова, выполняет свои действия в фоновом режиме)

4) Передача данных

- передающие (участвуют в передаче данных)

- не передающие

Структура MPI программы.

1) Включение библиотеки MPI

#include “mpi.h”

2) Часть программы до инициализации MPI. Здесь нельзя вызывать функции MPI, кроме функции:

Int MPI_Initialize(int *flag) - возвращает код ошибки, в качестве параметра возвращает адрес

Пример:

int a;

MPI_Initialized(&a);

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

Инициализация MPI производиться путем вызова функции:

int MPI_Init(int *argc, char ***argv);

argc – рассылка числа параметров командной строки

argv – рассылка массива параметров

3) Работа с MPI функциями. Оп окончании вызывается функция

int MPI_Finalize();

Она завершает работу программы с MPI.

4) Часть программы, где работают с функциями MPI вызывать MPI_Finalize() нельзя, но можно

int MPI_Finalized(int *flag);

Она аналогична проверяет была ли выполнена команда MPI_Finalize или нет.

Пример программы.

#include <stdio.h>

#include “mpi.h”

#define N 16

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

{ int rank, size, a, I, M[N];

MPI_Status;

MPI_Init(&argc,&argv);

MPI_Comm_size(MPI_COMM_WORLD,&size); //кол-во загружаемых процессов

MPI_Comm_rank(MPI_COMM_WORLD,&rank); //номера загружаемых процессов

a=3;

for (i=rank*N/size; i<(rank+1)*N/size; i++)

M[i]=a+i;

if (rank==0)

MPI_Recv(&M[rank*N/size],N/size,MPI_INT,1,0,MPI_COMM_WORLD,&status);

if (rank==1)

MPI_Send(&M[rank*N/size],N/size,MPI_INT,0,0,MPI_COMM_WORLD);

MPI_Finalize();

return 0;

}

  1. Стандарт MPI. Цели MPI. Операции поддерживаемые и неподдерживаемые в MPI. Идентификация в MPI. Двухточечные передачи в MPI (виды передач и функции для посылок и приемов сообщений). Примеры организации передач.

Стандарт MPI.

MPI – Message Passing Interface – интерфейс приема сообщений.

MPI – стандарт на программный инструментарий для обеспечения связей между ветвями параллельной программы. Стандарт MPI определяет синтаксис, семантику библиотечных функций, используемых при написании параллельных программ с передачей сообщений на языках Fortran, C, C++. MPI предоставляет единый механизм взаимодействия ветвей параллельной программы, независимо от машинной архитектуры, расположения ветвей по процессорам и API операционных систем. MPI поддерживает архитектуры: одно- и многопроцессорные. С общей и распределенной памятью. Программы, использующие MPI, легче отлаживаются и быстрее переносятся на другие платформы, в идеале просто перекомпиляцией.

Операции, поддерживаемые в MPI:

1.Операции взаимодействия процесс-процесс (двухточечная передача) MPI_Send

2.Коллективные операции. MPI_Bast – пересылка от одного ко всем.

3.Операции над группами процессов (пример операции над группами: создание, пересечение, сравнение и т.д.).

4.Операции над областями связи.

5.Операции над топологиями процессов.

6.Операции с типами данных.

7. Вспомогательная синхронизация и замеры времени.

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

Операции не поддерживаемые в MPI:

1) Явные операции с разделяемой памятью.

  1. Средства конструирования программ.

  2. Средства отладки.

  3. Операции с большей поддержкой ОС.

  4. Функции ввода-вывода на периферию.

Идентификация в MPI

Три типа идентификаторов:

1)Идентификаторы типов данных. Пример: MPI_Status

2)Определенные константы. Эти константы, которые могут вводиться в виде имени. В разных версиях MPI могут быть разные числа. Идентификаторы переопределенных констант всегда пишутся с заглавной буквы. Пример:

MPI_COMM_WORLD, MPI_INIT

3)Идентификаторы функций библиотеки. Строятся по двум шаблонам:

- MPI_<имя категории функции>_<имя операции>(MPI_Comm_size)

- MPI_<имя операции> (MPI_Send)

<имя категории функции> - первая буквы заглавная, остальные маленькие

<имя операции> - всегда маленькими

Двухточечные передачи в MPI

Двухточечные передачи состоят из двух частей – посылки сообщения и приема.

Передачи могут выполняться в трех режимах:

- блокирующем;

- неблокирующем (процесс, вызвавший функцию передачи продолжает выполняться, а процедура приема-передачи идет в фоновом режиме);

- отложенном.

Функции с блокирующей посылкой и блокирующим приемом данных:

Обычная асинхронная посылка

Int MPI_Send(void *buf, int count MPI_Datatype datatype, int dest, int msgtag, MPI_Comm comm);

buf – адрес начала передаваемого блока данных; datatype – тип посылаемых элементов

dest – номер процесса получателя; msgtag – тег сообщения; comm – идентификатор (id) области связи, в которой осуществляется передача.

Эта функция блокирует вызывающий ее процесс до тех пор пока не считает все данные из памяти и не передаст их в какой либо системный буфер.

Блокирующий прием данных

Int MPI_Recv(void *buf, int count MPI_Datatype datatype, int source, int msgtag, MPI_Comm comm, MPI_Status *status);

Status – переменная структура с параметрами принимаемого сообщения (Он ссылается на запись с двумя полями: одно - для источника, другое - для тэга. Например, если в качестве источника был указан MPI_ANY_SOURCE, то status будет содержать ранг процесса, который прислал сообщение)

Функция блокирует вызывающий ее процесс до тех пор пока данные не будут получены в полном объеме и полностью сохранены в памяти принимающего процесса.

Тэг при приеме/передаче должен совпадать. Если неизвестно от какого процесса будет приниматься сообщение, то ставиться вместо source константа MPI_ANY_SOURSE, вместо тэга – MPI_ANY_TAG.

Используя MPI_Status, можно получить статус сообщения: номер отправителя, id сообщения, код ошибки.

Int MPI_Bsend(<аналогично MPI_Send>);

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

Int MPI_Ssend(<аналогично MPI_Send>);

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

Int MPI_Rsend(<аналогично MPI_Send>);

Блокирующая согласованная посылка. Посылающий процесс блокируется до тех пор, пока принимающий процесс не готов принимать сообщение. Не все реализации MPI поддерживают эту функцию.

Int MPI_Sendrecv(void *sbuf, int scount MPI_Datatype stype, int dest, int stag, void *rbuf, int rcount MPI_Datatype rtype, int source, int rtag, MPI_Comm comm, MPI_Status *status);

Эта функция одновременно посылает 1 сообщение и принимает другое. MPI решает что делать сначала: принимать или послать.

sbuf – адрес в памяти, откуда считываются данные для посылки; scount – число элементов в посылаемом сообщении; datatype – тип посылаемых элементов; dest – номер процесса получателя; stag – тег сообщения (номер посылаемого сообщения). Вторая половина аналогична, для приема данных. comm – идентификатор (id) области связи, в которой осуществляется передача.

Status – статус принимаемого сообщения.

Вспомогательные функции:

Int MPI_Probe(int source, int msgtag, MPI_Comm comm, MPI_Status *status);

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

Int MPI_Iprobe(int source, int msgtag, int *flag, MPI_Comm comm, MPI_Status *status);

Это не блокирующая функция. Возвращает flag = true, если имеется сообщение, которое может быть получено и которое соответствует образцу, описанному аргументами source, tag, и comm.

Не блокирующие передачи данных в MPI

Int MPI_Isend(<аналогично MPI_Send>, MPI_Request *request);

Не блокирующая асинхронная посылка. Позволяет сократить время, т.к. нет блокировки все в фоновом режиме; но данные могут быть искажены процессом.

request – переменная идентифицирующая не блокирующие процедуры.

Int MPI_Ibsend(<аналогично MPI_Isend>);

Int MPI_Issend(<аналогично MPI_Isend>);

Int MPI_Irsend(<аналогично MPI_Isend>);

Int MPI_Irecv(<аналогично MPI_Recv, кроме status его нет!>, MPI_Request *request);

На момент выхода из функции MPI_Irecv как правило никакого сообщения еще не получено.

Int MPI_Isendrecv(…);

Если процессу есть чем заняться, тогда эта функция более эффективна.

Вспомогательные функции

- Функции семейства MPI_Wait

int MPI_Wait(MPI_Request *request, MPI_Status *status);

Блокирует вызывающий ее процесс то тех пор пока не закончиться не блокирующая процедура идентифицируемая параметром request. По окончании процедуры происходит разблокировка процесса, а в параметре status возвращается статус завершенной процедуры приема.

Int MPI_Waitall(int count,MPI_Request *request, MPI_Status *status);

Блокирует вызывающий ее процесс, пока не завершатся все процедуры, указанные в массиве request. Число этих процедур задается count.

Int MPI_Waitany(int count,MPI_Request *request,int *index, MPI_Status *status);

Блокирует вызывающий ее процесс до завершения любой из процедур, указанных в параметре массиве request. Число этих процедур задается параметром count. index – номер завершившейся процедуры.

Int MPI_Waitsome(int incount, MPI_Request *request, int outcount, int *indexes, MPI_Status *status);

Аналог MPI_Waitany, только в случае завершения нескольких процессов она возвращает общее число outcount и их номера в массиве indexes

- Функции семейства MPI_Test

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

Int MPI_Test(MPI_Request *request, int *flag, MPI_Status *status);

Int MPI_Testall(int count, MPI_Request *request, int *flag, MPI_Status *status);

Int MPI_Testany(int count, MPI_Request *request, int *index, int *flag, MPI_Status *status);

Int MPI_Testsome(int incount, MPI_Request *request, int outcount, int *indexes, int *flag, MPI_Status *status);

Отложенные двухточечные передачи данных в MPI.

Протокол работы процесса с отложенной передачей разделяется на три этапа:

1) Инициализация отложенной процедуры (посылки или приема)

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

2) Запуск отложенной процедуры.

3) Проверка или ожидание завершения процедуры.

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

Int MPI_Send_init(void *buf, int count MPI_Datatype datatype, int dest, int msgtag, MPI_Comm comm, MPI_Request *request);

Int MPI_Bsend_init(void *buf, int count MPI_Datatype datatype, int dest, int msgtag, MPI_Comm comm, MPI_Request *request);

Int MPI_Ssend_init(void *buf, int count MPI_Datatype datatype, int dest, int msgtag, MPI_Comm comm, MPI_Request *request);

Int MPI_Rsend_init(void *buf, int count MPI_Datatype datatype, int dest, int msgtag, MPI_Comm comm, MPI_Request *request);

Int MPI_Recv_init(void *buf, int count MPI_Datatype datatype, int source, int msgtag, MPI_Comm comm, MPI_Request *request);

Функции запуска отложенной процедуры, идентифицируемой параметром request

Int MPI_Start(MPI_Request *request);

Int MPI_Startall(int count, MPI_Request *request);

В параметр count записывается размер массива request.

Пример использования функций неблокирующих передач. (придумывал сам, так что не обессудьте:)))

X=A*B+C*D+K*T

Y=A*B+C*D+Z*F

#include <stdio.h>

#include "mpi.h"

#include "func.h"

int main(int argc, char ** argv)

{ int size,rank;

float A[N][N], B[N][N], C[N][N], D[N][N], K[N][N], T[N][N], Z[N][N], F[N][N], X[N][N], Y[N][N];

MPI_Request request1, request2;

MPI_Status status1, status2;

inits(A,B,C,D,K,T,Z,F);

MPI_Init(&argc,&argv);

MPI_Comm_size(MPI_COMM_WORLD,&size); //size=число процессов

MPI_Comm_rank(MPI_COMM_WORLD,&rank); //rank=номер процесса

if (rank ==0)

{ //вычисление общего слагаемого А*В

sub(A,B);

//передача общего слагаемого А*В

MPI_Isend(A,N*N,MPI_FLOAT,1,0,MPI_COMM_WORLD,&request1);

//прием общего слогаемого С*D

MPI_Irecv(C,N*N,MPI_FLOAT,1,0,MPI_COMM_WORLD,&request2);

//расчет локального слогаемого K*T

sub(K,T);

//Ожидание передаи и приема все слогаемых

MPI_Wait(&request1,&status1);

MPI_Wait(&request2,&status2);

//Окончательный расчет

Add(A,C,K,X);

//Вывод результата

Out(X);

}

if (rank ==1)

{

//вычисление общего слагаемого А*В

sub(С,D);

//передача общего слагаемого C*D

MPI_Isend(C,N*N,MPI_FLOAT,0,0,MPI_COMM_WORLD,&request1);

//прием общего слогаемого A*B

MPI_Irecv(A,N*N,MPI_FLOAT,0,0,MPI_COMM_WORLD,&request2);

//расчет локального слогаемого K*T

sub(Z,F);

//Ожидание передаи и приема все слогаемых

MPI_Wait(&request1,&status1);

MPI_Wait(&request2,&status2);

//Окончательный расчет

Add(A,C,Z,Y);

//Вывод результата

Out(Y);

}

MPI_Finalize(); return 0; }

  1. Двухточечные передачи в MPI. Организация блокирующих и неблокирующих посылок/приемов сообщений. Функции (основные и вспомогательные), используемые при неблокирующих посылках и приемах сообщений. Примеры.

Двухточечные передачи в MPI

Двухточечные передачи состоят из двух частей – посылки сообщения и приема.

Передачи могут выполняться в трех режимах:

- блокирующем;

- не блокирующем (процесс, вызвавший функцию передачи продолжает выполняться, а процедура приема-передачи идет в фоновом режиме);

- отложенном.

Функции с блокирующей посылкой и блокирующим приемом данных:

Обычная асинхронная посылка

Int MPI_Send(void *buf, int count MPI_Datatype datatype, int dest, int msgtag, MPI_Comm comm);

buf – адрес начала передаваемого блока данных; datatype – тип посылаемых элементов;

dest – номер процесса получателя; msgtag – тег сообщения; comm. – идентификатор (id) области связи, в которой осуществляется передача

Эта функция блокирует вызывающий ее процесс до тех пор пока не считает все данные из

памяти и не передаст их в какой либо системный буфер.

Блокирующий прием данных

Int MPI_Recv(void *buf, int count MPI_Datatype datatype, int source, int msgtag, MPI_Comm comm,

MPI_Status *status);

Status – переменная структура с параметрами принимаемого сообщения (Он ссылается на запись

с двумя полями: одно - для источника, другое - для тэга. Например, если в качестве источника

был указан MPI_ANY_SOURCE, то status будет содержать ранг процесса, который прислал

сообщение)

Функция блокирует вызывающий ее процесс до тех пор пока дыне на будут получены в полном

объеме и полностью сохранены в памяти принимающего процесса.

Тэг при приеме/передаче должен совпадать. Если неизвестно от какого процесса будет

приниматься сообщение, то ставиться вместо source константа MPI_ANY_SOURSE, вместо тэга –

MPI_ANY_TAG.

Используя MPI_Status, можно получить статус сообщения: номер отправителя, id сообщения, код

ошибки.

Int MPI_Bsend(<аналогично MPI_Send>);

Блокирующая асинхронная буферизированная посылка. В отличии от MPI_Send создается

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

происходит разблокирование процесса.

Int MPI_Ssend(<аналогично MPI_Send>);

Функция блокирующей синхронной посылки. Процесс, вызывающий эту функцию, блокируется

до тех пор, пока посылаемое сообщение не будет полностью принято процессом получателем.

Int MPI_Rsend(<аналогично MPI_Send>);

Блокирующая согласованная посылка. Посылающий процесс блокируется до тех пор, пока

принимающий процесс не готов принимать сообщение. Не все реализации MPI поддерживают эту

функцию.

Int MPI_Sendrecv(void *sbuf, int scount MPI_Datatype stype, int dest, int stag, void *rbuf, int rcount MPI_Datatype rtype, int source, int rtag, MPI_Comm comm, MPI_Status *status);

Эта функция одновременно посылает 1 сообщение и принимает другое. MPI речает что делать сначала: принимать или послать.

sbuf – адрес в памяти, откуда считываются данные для посылки; scount – число элементов в посылаемом сообщении; datatype – тип посылаемых элементов; dest – номер процесса получателя

stag – тег сообщения (номер посылаемого сообщения). Вторая половина аналогична, для приема данных. comm – идентификатор (id) области связи, в которой осуществляется передача.

Status – статус принимаемого сообщения. Вспомогательные функции:

Int MPI_Probe(int source, int msgtag, MPI_Comm comm, MPI_Status *status);

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

Int MPI_Iprobe(int source, int msgtag, int *flag, MPI_Comm comm, MPI_Status *status);

Это не блокирующая функция. Возвращает flag = true, если имеется сообщение, которое может быть получено и которое соответствует образцу, описанному аргументами source, tag, и comm.

Не блокирующие передачи данных в MPI

Int MPI_Isend(<аналогично MPI_Send>, MPI_Request *request);

Не блокирующая асинхронная посылка. Позволяет сократить время, т.к. нет блокировки все в фоновом режиме; но данные могут быть искажены процессом.

request – переменная идентифицирующая не блокирующие процедуры.

Int MPI_Ibsend(<аналогично MPI_Isend>);

Int MPI_Issend(<аналогично MPI_Isend>);

Int MPI_Irsend(<аналогично MPI_Isend>);

Int MPI_Irecv(<аналогично MPI_Recv, кроме status его нет!>, MPI_Request *request);

На момент выхода из функции MPI_Irecv как правило никакого сообщения еще не получено.

Int MPI_Isendrecv(…);

Если процессу есть чем заняться, тогда эта функция более эффективна.

Вспомогательные функции

- Функции семейства MPI_Wait

int MPI_Wait(MPI_Request *request, MPI_Status *status);

Блокирует вызывающий ее процесс то тех пор пока не закончиться не блокирующая процедура идентифицируемая параметром request. По окончании процедуры происходит разблокировка процесса, а в параметре status возвращается статус завершенной процедуры приема.

Int MPI_Waitall(int count,MPI_Request *request, MPI_Status *status);

Блокирует вызывающий ее процесс, пока не завершатся все процедуры, указанные в массиве request. Число этих процедур задается count.

Int MPI_Waitany(int count,MPI_Request *request,int *index, MPI_Status *status);

Блокирует вызывающий ее процесс до завершения любой из процедур, указанных в параметре массиве request. Число этих процедур задается параметром count. index – номер завершившейся процедуры.

Int MPI_Waitsome(int incount, MPI_Request *request, int outcount, int *indexes, MPI_Status *status);

Аналог MPI_Waitany, только в случае завершения нескольких процессов она возвращает общее число outcount и их номера в массиве indexes

- Функции семейства MPI_Test

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

Int MPI_Test(MPI_Request *request, int *flag, MPI_Status *status);

Int MPI_Testall(int count, MPI_Request *request, int *flag, MPI_Status *status);

Int MPI_Testany(int count, MPI_Request *request, int *index, int *flag, MPI_Status *status);

Int MPI_Testsome(int incount, MPI_Request *request, int outcount, int *indexes, int *flag, MPI_Status *status);

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