Разделы презентаций


Разработка параллельных программ в системах с распределенной памятью

Содержание

ПланMPIPVM

Слайды и текст этой презентации

Слайд 1Разработка параллельных программ в системах с распределенной памятью
Судаков А.А.
“Параллельные и

распределенные вычисления” Лекция 22

Разработка параллельных программ в системах с распределенной памятьюСудаков А.А.“Параллельные и распределенные вычисления” Лекция 22

Слайд 2План
MPI
PVM

ПланMPIPVM

Слайд 3Литература
http://www.mpi-forum.org/docs/docs.html
http://www.cluster.kiev.ua/support/documentation/
http://www.cluster.kiev.ua/support/documentation/pvm3/book/pvm-book.html



Литератураhttp://www.mpi-forum.org/docs/docs.htmlhttp://www.cluster.kiev.ua/support/documentation/http://www.cluster.kiev.ua/support/documentation/pvm3/book/pvm-book.html

Слайд 4Интерфейсы разработки параллельных программ
API для распределенного программирования не рассчитаны на

разработку сложных схем обмена между процессами
Для этого разработаны специальные интерфейсы

Интерфейсы разработки параллельных программAPI для распределенного программирования не рассчитаны на разработку сложных схем обмена между процессамиДля этого

Слайд 5Стандарт MPI
Стандарт интерфейса обмена сообщениями
Гарантируется совместимость на уровне исходного

кода C и Fortran
Существует множество реализаций
mpich
LAM
SCALI
..
По исполняемому коду, протоколу передачи

и др. совместимость не гарантируется
MPI – надстройка над сокетами, общей памятью и др.
Стандарт MPIСтандарт интерфейса обмена сообщениями Гарантируется совместимость на уровне исходного кода C и FortranСуществует множество реализацийmpichLAMSCALI..По исполняемому

Слайд 6Основные понятия
MPI программа – набор параллельно выполняющихся процессов, которые могут

обмениваться между собой сообщениями
Для обмена сообщениями процессы объединяются в группы

– коммуникаторы или коммуникационные области (домены)
MPI предоставляют функции обмена сообщениями внутри любых коммуникационных доменов
С помощью библиотеки MPI каждый процесс может определить свой номер внутри домена и выполнять необходимую часть расчетов (SIMD, MISD, MIMD)
Все процессы выполняют один и тот же исполняемый файл
Разные процессы выполняют разные исполняемые файлы
Каждое сообщение имеет свой номер – идентификатор, по которому сообщения можно отличать друг от друга
Основные понятияMPI программа – набор параллельно выполняющихся процессов, которые могут обмениваться между собой сообщениямиДля обмена сообщениями процессы

Слайд 7Запуск MPI машины
Зависит от реализации
Программы на других машинах запускаются командой

$LAMRSH
export LAMRSH="rsh“
Виртуальная машина запускается командой
lamboot
Первой в

списке должна быть локальная машина
node1
node2
Запуск MPI машиныЗависит от реализацииПрограммы на других машинах запускаются командой $LAMRSHexport LAMRSH=

Слайд 8Запуск программ
mpirun –np

Запуск программmpirun –np

Слайд 9Структура MPI программы
Все процессы чаще всего выполняют один и тот

же исполняемый файл
Первой MPI функцией должна быть вызвана
MPI_Init( &argc,

&argv )
Последней одна из функций
MPI_Finalize() - нормальное завершение
MPI_Abort( описатель области связи, код ошибки MPI ); - завершение с сообщением об ошибке
Между этими вызовами можно вызывать любые функции MPI
Структура MPI программыВсе процессы чаще всего выполняют один и тот же исполняемый файлПервой MPI функцией должна быть

Слайд 10Основной коммуникационный домен
Все процессы выполняют один исполняемый файл
Все процессы принадлежат

основному коммуникационному домену с именем MPI_COMM_WORLD
Каждому процессу после запуска присваивается

номер
Для любого коммуникационного домена каждый процесс может узнать свой номер и общее количество процессов в домене
int size, rank;
MPI_Comm_size( MPI_COMM_WORLD, &size ); - количество процессов в домене
MPI_Comm_rank( MPI_COMM_WORLD, &rank ); - номер процесса в домене
Эти вызовы - только после MPI_Init
Основной коммуникационный доменВсе процессы выполняют один исполняемый файлВсе процессы принадлежат основному коммуникационному домену с именем MPI_COMM_WORLDКаждому процессу

Слайд 11Пример MPI программы
int main(int argc, char* argv[]){

int my_number; //Мой номер процесса
int proc_num;

//общее количество процессов

MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &proc_num);
MPI_Comm_rank(MPI_COMM_WORLD, &my_number);

printf("I an process %d, sending data\n", my_number);

MPI_Finalize();
return 0;
}
Пример MPI программыint main(int argc, char* argv[]){    int my_number; 	//Мой номер процесса

Слайд 12Создание новых коммуникационных доменов
Иногда необходимо организовать обмен между процессами параллельно

с обменом в основном коммуникационном домене
Чтобы теги сообщений повторялись
Чтобы выполнять

коллективные операции обмена
Алгоритм Фокса
Это делается путем создания нового коммуникационного домена
Копированием существующего
Разделением существующего на поддомены
Отображение групп на коммуникационные домены
Создание новых коммуникационных доменовИногда необходимо организовать обмен между процессами параллельно с обменом в основном коммуникационном доменеЧтобы теги

Слайд 13Копирование доменов
Создание копии существующего домена
Обмен в новом домене не перекрывается

с обменом в старом
Все процессы старого коммуникатора должны вызвать

эту функцию
MPI_Comm tempComm; MPI_Comm_dup( MPI_COMM_WORLD, &tempComm ); /* ... передаем данные через tempComm ... */ MPI_Comm_free( &tempComm );
Копирование доменовСоздание копии существующего доменаОбмен в новом домене не перекрывается с обменом в старом Все процессы старого

Слайд 14Разбиение существующего домена на части
Существующий коммуникатор можно разбить на части
Все

процессы старого коммуникатора должны вызвать эту функцию
Все процессы с одинаковым

«цветом» (задается) попадают в один коммуникатор
Номер процесса в новом коммуникаторе задается
MPI_Comm_split( existingComm, /* расщепляемый описатель ( MPI_COMM_WORLD) */ indexOfNewSubComm, /* номер подгруппы, куда попадает вызывающий процесс */ rankInNewSubComm, /* желательный номер в новой подгруппе */ &newSubComm ); /* описатель области связи новой подгруппы */
Разбиение существующего домена на частиСуществующий коммуникатор можно разбить на частиВсе процессы старого коммуникатора должны вызвать эту функциюВсе

Слайд 15Пример расщепления
#include "mpi.h"
int main(int argc, char* argv[]){
MPI_Comm subComm;
int size,

rank, subrank, subsize;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank( MPI_COMM_WORLD, &rank );

//разбиваем набор процессов на

3 группы
//нумерация процессов в каждой группе 0-2
MPI_Comm_split(MPI_COMM_WORLD, rank/3, rank%3, &subComm);

MPI_Comm_rank( subComm, &subrank );
MPI_Comm_size( subComm, &subsize );
printf("old size = %d new size %d ",size, subsize);
printf("old rank = %d new rank %d\n",rank, subrank);
MPI_Comm_free(&subComm);
MPI_Finalize();
return 0;
}

Пример расщепления #include

Слайд 16Компиляция и выполнения
[saa@cluster mpi]$ mpicc ./comm_split.c -o comm_split
[saa@cluster mpi]$ mpirun

-np 10 -wd /net/s1/$PWD ./comm_split
old size = 10 new size

1 old rank = 9 new rank 0
old size = 10 new size 3 old rank = 8 new rank 2
old size = 10 new size 3 old rank = 6 new rank 0
old size = 10 new size 3 old rank = 7 new rank 1
old size = 10 new size 3 old rank = 0 new rank 0
old size = 10 new size 3 old rank = 1 new rank 1
old size = 10 new size 3 old rank = 2 new rank 2
old size = 10 new size 3 old rank = 4 new rank 1
old size = 10 new size 3 old rank = 5 new rank 2
old size = 10 new size 3 old rank = 3 new rank 0

Компиляция и выполнения[saa@cluster mpi]$ mpicc ./comm_split.c -o comm_split[saa@cluster mpi]$ mpirun -np 10 -wd /net/s1/$PWD ./comm_splitold size =

Слайд 17Создание коммуникатора на базе группы
Создается группа процессов на базе существующего

коммуникатора
В/из группы добавляются/удаляются номера процессов
На базе группы создается новый коммуникатор
Все

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

Создание коммуникатора на базе группыСоздается группа процессов на базе существующего коммуникатораВ/из группы добавляются/удаляются номера процессовНа базе группы

Слайд 18Создание группы на базе коммуникатора
Группа – набор номеров процессов
Может выполнить

каждый процесс параллельной программы
В каждом процессе можно создавать свои группы
MPI_Group

group;
MPI_Comm_group(MPI_COMM_WORLD, &group);
Создание группы на базе коммуникатораГруппа – набор номеров процессовМожет выполнить каждый процесс параллельной программыВ каждом процессе можно

Слайд 19Операции с группами
Удаление процессов из группы
Добавление процессов в группы
Объединение групп
Удаление

групп
MPI_Group group, subgroup;
int ranks[5], i;
for(i = 0; i

Операции с группамиУдаление процессов из группыДобавление процессов в группыОбъединение группУдаление группMPI_Group group, subgroup;int ranks[5], i;for(i = 0;

Слайд 20Создание нового коммуникатора на базе группы
MPI_Comm subComm;
MPI_Group subgroup;
MPI_Comm_create(MPI_COMM_WORLD, subgroup,&subComm);

Создание нового коммуникатора на базе группыMPI_Comm subComm;MPI_Group subgroup;MPI_Comm_create(MPI_COMM_WORLD, subgroup,&subComm);

Слайд 21Пример работы с группами
#include "mpi.h"
int main(int argc, char* argv[]){

MPI_Comm subComm;
int size, rank,

subrank, subsize,i;
int ranks[5];
MPI_Group group, subgroup;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank( MPI_COMM_WORLD, &rank );
MPI_Comm_group(MPI_COMM_WORLD, &group);
for(i = 0; i<5; i++) ranks[i]=i;
MPI_Group_excl(group,5,ranks,&subgroup);
MPI_Comm_create(MPI_COMM_WORLD, subgroup,&subComm);
if( subComm == MPI_COMM_NULL) {
printf ("%d not in communicator\n",rank);
} else {
MPI_Comm_rank( subComm, &subrank );
MPI_Comm_size( subComm, &subsize );
printf("old size = %d new size %d ",size, subsize);
printf("old rank = %d new rank %d\n",rank, subrank);
}
if( subComm != MPI_COMM_NULL) MPI_Comm_free(&subComm);
MPI_Group_free(&subgroup);
MPI_Group_free(&group);
MPI_Finalize();
return 0;
}

Пример работы с группами#include

Слайд 22Компиляция и выполнение
[saa@cluster mpi]$ mpicc ./comm_group.c -o comm_group
[saa@cluster mpi]$ mpirun

-np 10 -wd /net/s1/$PWD ./comm_group
2 not in communicator
0 not in

communicator
1 not in communicator
4 not in communicator
3 not in communicator
old size = 10 new size 5 old rank = 8 new rank 3
old size = 10 new size 5 old rank = 9 new rank 4
old size = 10 new size 5 old rank = 5 new rank 0
old size = 10 new size 5 old rank = 6 new rank 1
old size = 10 new size 5 old rank = 7 new rank 2

Компиляция и выполнение[saa@cluster mpi]$ mpicc ./comm_group.c -o comm_group[saa@cluster mpi]$ mpirun -np 10 -wd /net/s1/$PWD ./comm_group2 not in

Слайд 23Получение имени машины, где работает процесс
char nm[4096];
int name_size = 4096;

MPI_Get_processor_name(nm, &nm_size);

Получение имени машины, где работает процессchar nm[4096];int name_size = 4096; MPI_Get_processor_name(nm, &nm_size);

Слайд 24Операции передачи данных
Все передачи данных выполняются в пределах коммуникатора
Данные пересылаются

в виде сообщений
Сообщение имеет номер (тег)
В одном сообщении могут быть

данные любой сложности
Операции передачи данных
Точка-точка
Коллективные
Broadcst
Reduce
Синхронные – блокируется пока не завершится
Асинхронные – не блокируется
Операции передачи данныхВсе передачи данных выполняются в пределах коммуникатораДанные пересылаются в виде сообщенийСообщение имеет номер (тег)В одном

Слайд 25Операции точка-точка (блокирующие)
Передача
int buf[10];
MPI_Send( buf, 5, MPI_INT, 1, 0,

MPI_COMM_WORLD );
Прием
int buf[10];
MPI_Status status;
MPI_Recv( buf, 10, MPI_INT,

0, 0, MPI_COMM_WORLD, &status );
Аргументы
Буфер данных
Количество элементов данных
Тип каждого элемента данных буфера
Номер процесса кому/от кого передавать/принимать
Может быть MPI_ANY_SOURCE
Тег сообщения
Может быть MPI_ANY_TAG
Коммуникатор в каком передавать
Результат операции (только для приема)
Операции точка-точка (блокирующие)Передачаint buf[10]; MPI_Send( buf, 5, MPI_INT, 1, 0, MPI_COMM_WORLD ); Приемint buf[10]; MPI_Status status; MPI_Recv(

Слайд 26Результат операции (статус)
Данные могут прийти
неизвестно от кого
С неизвестным тегом
В

неизвестном количестве
При приеме может возникнуть ошибка
Определение количества данных
MPI_Status status; int

count; MPI_Recv( ... , MPI_INT, ... , &status ); MPI_Get_count( &status, MPI_INT, &count ); /* ... теперь count содержит количество принятых ячеек */
Результат операции (статус)Данные могут прийти неизвестно от когоС неизвестным тегомВ неизвестном количествеПри приеме может возникнуть ошибкаОпределение количества

Слайд 27Коллективные (распределенные) операции
MPI_Broadcast
MPI_Reduce
MPI_Gather
MPI_Scatter
MPI_All_Gather

Выполняются всеми процессами для эффективного выполнения суммирования, умножения

Коллективные (распределенные) операцииMPI_BroadcastMPI_ReduceMPI_GatherMPI_ScatterMPI_All_Gather…Выполняются всеми процессами для эффективного выполнения суммирования, умножения …

Слайд 28
#include "mpi.h"
int main(int argc, char* argv[]){
MPI_Comm subComm;
int size, rank, subrank,

subsize;
int vector[16],i;
int resultVector[16];
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank( MPI_COMM_WORLD, &rank );

for( i=0; i

) vector[i] = rank*100 + i;

MPI_Reduce(
vector, /* каждая задача в коммуникаторе предоставляет вектор */
resultVector, /* задача номер 'root' собирает данные сюда */
16, /* количество ячеек в исходном и результирующем массивах */
MPI_INT, /* тип элемента данных */
MPI_SUM, /* описатель операции: поэлементное сложение векторов */
0, /* номер задачи, собирающей результаты в 'resultVector' */
MPI_COMM_WORLD /* описатель области связи */
);
if( rank==0 ) for(i=0; i<16; i++)
printf("resultVector[%d]=%d ",i,resultVector[i]);
MPI_Finalize();
return 0;
}

#include

Слайд 29Пример выполнения
[saa@cluster mpi]$ mpirun -np 10 -wd /net/s1/$PWD ./reduce
resultVector[0]=4500 resultVector[1]=4510

resultVector[2]=4520 resultVector[3]=4530 resultVector[4]=4540 resultVector[5]=4550 resultVector[6]=4560 resultVector[7]=4570 resultVector[8]=4580 resultVector[9]=4590 resultVector[10]=4600 resultVector[11]=4610

resultVector[12]=4620 resultVector[13]=4630 resultVector[14]=4640 resultVector[15]=4650
Пример выполнения[saa@cluster mpi]$ mpirun -np 10 -wd /net/s1/$PWD ./reduceresultVector[0]=4500 resultVector[1]=4510 resultVector[2]=4520 resultVector[3]=4530 resultVector[4]=4540 resultVector[5]=4550 resultVector[6]=4560 resultVector[7]=4570 resultVector[8]=4580

Слайд 30Типы данных
На разных аппаратных платформах одинаковые типы данных представляются по

разному
Необходимо при передаче преобразовывать представления данных (XDR)
Для каждого типа своя

функция преобразования
Можно создавать свои типы данных, которые тоже будут передаваться корректно
Типы данныхНа разных аппаратных платформах одинаковые типы данных представляются по разномуНеобходимо при передаче преобразовывать представления данных (XDR)Для

Слайд 31Встроенные типы данных
C
MPI_CHAR MPI_SHORT MPI_INT MPI_LONG MPI_UNSIGNED_CHAR MPI_UNSIGNED_SHORT MPI_UNSIGNED_LONG MPI_UNSIGNED

MPI_FLOAT MPI_DOUBLE MPI_LONG_DOUBLE MPI_BYTE MPI_PACKED
Fortran
MPI_CHARACTER MPI_INTEGER MPI_REAL MPI_DOUBLE_PRECISION

MPI_COMPLEX MPI_DOUBLE_COMPLEX MPI_LOGICAL MPI_BYTE MPI_PACKED
Встроенные типы данныхC	MPI_CHAR  MPI_SHORT  MPI_INT  MPI_LONG  MPI_UNSIGNED_CHAR  MPI_UNSIGNED_SHORT  MPI_UNSIGNED_LONG  MPI_UNSIGNED

Слайд 32Создание новых типов данных
Для сложных структур данных можно создать свой

тип
Это упрощает сериализацию
Новый тип создается на основе уже существующих

Создание новых типов данныхДля сложных структур данных можно создать свой типЭто упрощает сериализациюНовый тип создается на основе

Слайд 33Функции создания новых типов данных
MPI_Type_struct( count, /* количество полей */

int *len, /* массив с длинами полей */ /* (на

тот случай, если это массивы) */ MPI_Aint *pos, /* массив со смещениями полей */ /* от начала структуры, в байтах */ MPI_Datatype *types, /* массив с описателями типов полей */ MPI_Datatype *newtype ); /* ссылка на создаваемый тип */
Функции создания новых типов данныхMPI_Type_struct(  count, 		/* количество полей */  int *len, 	/* массив с

Слайд 34Пример создания типа структуры
#include /* подключаем макрос 'offsetof()' */
typedef

struct {
int i;
double d[3];
long l[8];
char c;


} AnyStruct;

AnyStruct st;
MPI_Datatype anyStructType;

int len[5] = { 1, 3, 8, 1, 1 };
MPI_Aint pos[5] = { offsetof(AnyStruct,i), offsetof(AnyStruct,d), offsetof(AnyStruct,l),
offsetof(AnyStruct,c), sizeof(AnyStruct)
};

MPI_Datatype typ[5] = { MPI_INT,MPI_DOUBLE,MPI_LONG,MPI_CHAR,MPI_UB };
MPI_Type_struct( 5, len, pos, typ, &anyStructType );
MPI_Type_commit( &anyStructType ); /* подготовка закончена */

MPI_Send( st, 1, anyStructType, ... );
Пример создания типа структуры#include /* подключаем макрос 'offsetof()' */typedef struct { 	int i; 	double d[3]; 	long l[8];

Слайд 35Упаковка данных (сериализация)
Упаковка – запись разнотипных структур данных в один

массив
int MPI_Pack(void *buf, int count, MPI_Datatype dtype, void *packbuf, int

packsize, int *packpos, MPI_Comm comm)
INPUT PARAMETERS
buf - input buffer start (choice)
count - number of input data items (integer)
dtype - datatype of each input data item (handle)
packsize - output buffer size, in bytes (integer)
comm - communicator for packed message (handle)

INPUT/OUTPUT PARAMETER
packpos - current position in buffer, in bytes (integer)

OUTPUT PARAMETER
packbuf - output buffer start (choice)
Упаковка данных (сериализация)Упаковка – запись разнотипных структур данных в один массивint MPI_Pack(void *buf, int count, MPI_Datatype dtype,

Слайд 36Распаковка данных
int MPI_Unpack(void *packbuf, int packsize, int *packpos,
void

*buf, int count, MPI_Datatype dtype, MPI_Comm comm)

INPUT PARAMETERS

packbuf - input buffer start (choice)
packsize - size of input buffer, in bytes (integer)
count - number of items to be unpacked (integer)
dtype - datatype of each output data item (handle)
comm - communicator for packed message (handle)

INPUT/OUTPUT PARAMETERS
packpos - current position in bytes (integer)

OUTPUT PARAMETER
buf - output buffer start (choice)

Распаковка данныхint MPI_Unpack(void *packbuf, int packsize, int *packpos,  void *buf, int count, MPI_Datatype dtype, MPI_Comm comm)INPUT

Слайд 37Пример упаковки-распаковки
#define msgTag 10
struct {
int i;
float f[4];


char c[8];
} s;

Передача
int bufPos = 0;
char tempBuf[

sizeof(s) ];
MPI_Pack(&s.i, 1, MPI_INT, tempBuf, sizeof(tempBuf), &bufPos, MPI_COMM_WORLD );
MPI_Pack( s.f, 4, MPI_FLOAT, tempBuf, sizeof(tempBuf), &bufPos, MPI_COMM_WORLD );
MPI_Pack( s.c, 8, MPI_CHAR, tempBuf, sizeof(tempBuf), &bufPos, MPI_COMM_WORLD );
MPI_Send( tempBuf, bufPos, MPI_BYTE, targetRank, msgTag, MPI_COMM_WORLD );

Прием
int bufPos = 0;
char tempBuf[ sizeof(s) ];
MPI_Recv( tempBuf, sizeof(tempBuf), MPI_BYTE, sourceRank, msgTag, MPI_COMM_WORLD, &status );
MPI_Unpack( tempBuf, sizeof(tempBuf), &bufPos,&s.i, 1, MPI_INT, MPI_COMM_WORLD);
MPI_Unpack( tempBuf, sizeof(tempBuf), &bufPos, s.f, 4, MPI_FLOAT,MPI_COMM_WORLD);
MPI_Unpack( tempBuf, sizeof(tempBuf), &bufPos, s.c, 8, MPI_CHAR, MPI_COMM_WORLD);
Пример упаковки-распаковки#define msgTag 10 struct { 	int i; 	float f[4]; 	char c[8]; } s;Передача int bufPos =

Слайд 38Асинхронные операции
Функция приема-передачи не блокируется
Прием-передачу можно выполнять параллельно с обработкой

данных
К передаваемым данным нельзя обращаться в процессе передачи-приема
Необходимо специально проверять

завершение операции
Асинхронные операцииФункция приема-передачи не блокируетсяПрием-передачу можно выполнять параллельно с обработкой данныхК передаваемым данным нельзя обращаться в процессе

Слайд 39Функции асинхронной передачи-приема
MPI_Isend (&buf,count,datatype,dest,tag,comm,&request)
MPI_Irecv (&buf,count,datatype,source,tag,comm,&request)

Все параметры аналогичные
Добавляется еще

один
Статус выполнения запроса request

Функции асинхронной передачи-приемаMPI_Isend (&buf,count,datatype,dest,tag,comm,&request) MPI_Irecv (&buf,count,datatype,source,tag,comm,&request) Все параметры аналогичныеДобавляется еще одинСтатус выполнения запроса request

Слайд 40Проверка состояния
Проверка
MPI_Test(MPI_Request *req, int *flag, MPI_Status *stat)
Статус может быть MPI_STATUS_IGNORE
Ожидание

завершения
MPI_Wait(MPI_Request *preq, MPI_Status *stat)

Ожидание завершения нескольких запросов
int MPI_Waitall(int count, MPI_Request

*reqs, MPI_Status *stats)
Проверка состоянияПроверкаMPI_Test(MPI_Request *req, int *flag, MPI_Status *stat)Статус может быть MPI_STATUS_IGNOREОжидание завершенияMPI_Wait(MPI_Request *preq, MPI_Status *stat)Ожидание завершения нескольких запросовint

Слайд 41Пример асинхронной операции
MPI_Request reqs[4];
MPI_Status stats[4];

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]);

{ do some work }

MPI_Waitall(4, reqs, stats);
Пример асинхронной операцииMPI_Request reqs[4]; MPI_Status stats[4]; MPI_Irecv(&buf[0], 1, MPI_INT, prev, tag1, MPI_COMM_WORLD, &reqs[0]); MPI_Irecv(&buf[1], 1, MPI_INT, next,

Слайд 42Расширенные возможности MPI-2
Параллельный ввод-вывод в разные части файла
Доступ к памяти

на удаленной машине
Синхронизация
Создание и остановка процессов
Присоединение к работающей программе

Расширенные возможности MPI-2Параллельный ввод-вывод в разные части файлаДоступ к памяти на удаленной машинеСинхронизацияСоздание и остановка процессовПрисоединение к

Слайд 43PVM
Рассчитана на гетерогенные системы
Функции
Управление процессами
Упаковка – распаковка данных
Прием –

передача сообщений
Управление буфером сообщений
Функции управления системой PVM

PVM Рассчитана на гетерогенные системыФункцииУправление процессамиУпаковка – распаковка данныхПрием – передача сообщенийУправление буфером сообщенийФункции управления системой PVM

Слайд 44Параллельная машина
Создается путем запуска демонов на соответствующих хостах
Имеет общую среду

управления
Все системные переменные указанные в системной переменной PVM_EXPORT экспортируются на

все процессы задачи
export DISPLAY=myworkstation:0.0
export MYSTERYVAR=13
export PVM_EXPORT=“DISPLAY:MYSTERYVAR”
Машины можно добавлять через командную строку - pvm
По умолчанию все программы должны находится в каталогах
$PVM_ROOT
~pvm3/bin/$PVM_ARCH/
Параллельная машинаСоздается путем запуска демонов на соответствующих хостахИмеет общую среду управленияВсе системные переменные указанные в системной переменной

Слайд 45Запуск параллельной машины
Машина запускается командой
pvm
При этом запускается демон на

локальной машине
Запуск программ на других машинах выполняется через команду $PVM_RSH
export

PVM_RSH="/usr/bin/rsh“
На всех машинах должны быть установлены системные переменные
PVM_ARCH PVM_ROOT PVM_RSH XPVM_ROOT
export PVM_ARCH="LINUXI386“
export PVM_ROOT="/usr/share/pvm3“
export PVM_RSH="/usr/bin/rsh“
Это можно сделать в файле
~/.bashrc
Запуск параллельной машиныМашина запускается командой pvmПри этом запускается демон на локальной машинеЗапуск программ на других машинах выполняется

Слайд 46Функции управления процессами
Создание процессов
int numt = pvm_spawn(
char *task, //

имя программы
char **argv, // набор аргументов программы
int flag, //

особенность интерпретации // аргументов программы
char *where, // масив имен машин
int ntask, // количество заданий
int *tids ) // возвращаются
// идентификаторы заданий
Функции управления процессамиСоздание процессовint numt = pvm_spawn( char *task, 	// имя программы char **argv, 	// набор аргументов

Слайд 47Функции управления процессами
int pvm_kill (int taskid) – завершение другого процесса
pvm_exit()

– завершение своего процесса

Функции управления процессамиint pvm_kill (int taskid) – завершение другого процессаpvm_exit() – завершение своего процесса

Слайд 48Управление виртуальной машиной
Добавление физических машин
int info = pvm_addhosts( char **hosts,

int nhost, int *infos )
Удаление физических машин
int info = pvm_delhosts(

char **hosts, int nhost, int *infos )
Остановка виртуальной машины
pvm_halt()

Управление виртуальной машинойДобавление физических машинint info = pvm_addhosts( char **hosts, int nhost, int *infos )Удаление физических машинint

Слайд 49Пример
#include
#include

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

char* hosts[]={"node1", "node2", "node3"};
int tids[16];

int status[3];
int ntasks, nhosts;
char* task="/net/node1/home/saa/src/parallel_and_distributed/pvm/create";
char* arg[]={"child",NULL};

if(argc <2){
nhosts = pvm_addhosts(hosts,3,status);
printf("added %d hosts\n",nhosts);
ntasks = pvm_spawn(task,arg,0,NULL,16,tids);
printf("spawned %d tasks\n",ntasks);
pvm_halt();
}

return 0;
}

Пример#include #include int main (int argc, char* argv[]){    char* hosts[]={

Слайд 50Пример выполнения и компиляции
[saa@cluster pvm]$ gcc ./create.c -I$PVM_ROOT/include -L$PVM_ROOT/lib/$PVM_ARCH -lpvm3

-o create
/usr/share/pvm3/lib/LINUXI386/libpvm3.a(lpvmgen.o)(.text+0x292): In function `pvmlogperror':
: warning: `sys_errlist' is deprecated; use

`strerror' or `strerror_r' instead
/usr/share/pvm3/lib/LINUXI386/libpvm3.a(lpvmgen.o)(.text+0x289): In function `pvmlogperror':
: warning: `sys_nerr' is deprecated; use `strerror' or `strerror_r' instead
[saa@cluster pvm]$ pvm
pvm> quit

Console: exit handler called
pvmd still running.
[saa@cluster pvm]$ ./create
added 2 hosts
spawned 16 tasks
Terminated

Пример выполнения и компиляции[saa@cluster pvm]$ gcc ./create.c -I$PVM_ROOT/include -L$PVM_ROOT/lib/$PVM_ARCH -lpvm3 -o create/usr/share/pvm3/lib/LINUXI386/libpvm3.a(lpvmgen.o)(.text+0x292): In function `pvmlogperror':: warning: `sys_errlist'

Слайд 51Прием и отправка сообщений
Инициализация буфера упаковки
Упаковка
Отправка


Прием и отправка сообщенийИнициализация буфера упаковкиУпаковкаОтправка

Слайд 52Инициализация буфера упаковки
Данные пакуются в специальный буфер
В системе может быть

несколько буферов
Один – существует по умолчанию
Буфер инициализируется с помощью функции
int

bufid = pvm_initsend( int encoding )
encoing – PvmDataDefault или 0 соответсвует XDR формату
Новый буфер можно создать и удалить
pvm_mkbuf(int encoding )
pvm_freebuf(int buf)
Для установки буфера по умолчанию
oldbuf = pvm_setrbuf( int bufid )
oldbuf = pvm_setsbuf( int bufid )
Инициализация буфера упаковкиДанные пакуются в специальный буферВ системе может быть несколько буферовОдин – существует по умолчаниюБуфер инициализируется

Слайд 53Упаковка и распаковка сообщений
Для сериализации существуют функции упаковки и распаковки

разных типов данных
Данные пакуются в буфер, используемый по умолчанию
Упаковка
pvm_pkbyte( char

*xp, int nitem, int stride )
pvm_pkdouble( double *dp, int nitem, int stride )
pvm_pkint( int *ip, int nitem, int stride )
pvm_pkstr( char *sp )
Распаковка
pvm_upkbyte( char *xp, int nitem, int stride)
pvm_upkdouble( double *dp, int nitem, int stride)
pvm_upkint( int *ip, int nitem, int stride)
pvm_upkstr( char *sp )
Аргументы
xp – указатель на буфер памяти откуда/куда будет выполняться операция
nitem – количество элементов массива одного типа для упаковки/распаковки
stride – через сколько элементов “перепрыгивать”
Упаковка и распаковка сообщенийДля сериализации существуют функции упаковки и распаковки разных типов данныхДанные пакуются в буфер, используемый

Слайд 54Отправка-прием
Данные отправляются и принимаются в буфер по умолчанию
Отправка
int pvm_send(int tid,

in tag)
Прием
int pvm_recv(int tid, in tag)
Проверка на наличие сообщений в

буфере
int pvm_nrecv(int tid, in tag)


Отправка-приемДанные отправляются и принимаются в буфер по умолчаниюОтправкаint pvm_send(int tid, in tag)Приемint pvm_recv(int tid, in tag)Проверка на

Слайд 55Пример программы
#include
#include
int main (int argc, char* argv[]){

char* hosts[]={"node1", "node2", "node3"};
int

tids[16];
int status[3];
char message[4096];
int ntasks, nhosts,i;
char* task="/net/node1/home/saa/src/parallel_and_distributed/pvm/msg";
char* arg[]={"child",NULL};

if(argc <2){ //parent
nhosts = pvm_addhosts(hosts,3,status);
printf("added %d hosts\n",nhosts);
ntasks = pvm_spawn(task,arg,0,"",16,tids);
printf("spawned %d tasks\n",ntasks);
for (i = 0; i<16;i++){
pvm_recv(tids[i],1);
pvm_upkstr(message);
printf("child %d work at %s\n",i,message);
}
pvm_halt();
} else {
pvm_initsend(PvmDataDefault);
gethostname(message,4096);
pvm_pkstr(message);
pvm_send(pvm_parent(),1);
pvm_exit();
}

return 0;
}

Пример программы#include #include int main (int argc, char* argv[]){    char* hosts[]={

Слайд 56Пример выполнения
[saa@cluster pvm]$ gcc ./msg.c -I$PVM_ROOT/include -L$PVM_ROOT/lib/$PVM_ARCH -lpvm3 -o msg
/usr/share/pvm3/lib/LINUXI386/libpvm3.a(lpvmgen.o)(.text+0x292):

In function `pvmlogperror':
: warning: `sys_errlist' is deprecated; use `strerror' or

`strerror_r' instead
/usr/share/pvm3/lib/LINUXI386/libpvm3.a(lpvmgen.o)(.text+0x289): In function `pvmlogperror':
: warning: `sys_nerr' is deprecated; use `strerror' or `strerror_r' instead
[saa@cluster pvm]$ pvm
pvm> quit

Console: exit handler called
pvmd still running.
[saa@cluster pvm]$ ./msg
added 2 hosts
spawned 16 tasks
child 0 work at ss20-2.univ.kiev.ua
child 1 work at ss20-2.univ.kiev.ua
child 2 work at ss20-2.univ.kiev.ua
child 3 work at ss20-2.univ.kiev.ua
child 4 work at ss20-2.univ.kiev.ua
child 5 work at ss20-2.univ.kiev.ua
child 6 work at ss20-3.univ.kiev.ua
child 7 work at ss20-3.univ.kiev.ua
child 8 work at ss20-3.univ.kiev.ua
child 9 work at ss20-3.univ.kiev.ua
child 10 work at ss20-3.univ.kiev.ua
child 11 work at cluster.univ.kiev.ua
child 12 work at cluster.univ.kiev.ua
child 13 work at cluster.univ.kiev.ua
child 14 work at cluster.univ.kiev.ua
child 15 work at cluster.univ.kiev.ua
Terminated

Пример выполнения[saa@cluster pvm]$ gcc ./msg.c -I$PVM_ROOT/include -L$PVM_ROOT/lib/$PVM_ARCH -lpvm3 -o msg/usr/share/pvm3/lib/LINUXI386/libpvm3.a(lpvmgen.o)(.text+0x292): In function `pvmlogperror':: warning: `sys_errlist' is deprecated;

Слайд 57Вопросы ?

Вопросы ?

Обратная связь

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

Email: Нажмите что бы посмотреть 

Что такое TheSlide.ru?

Это сайт презентации, докладов, проектов в PowerPoint. Здесь удобно  хранить и делиться своими презентациями с другими пользователями.


Для правообладателей

Яндекс.Метрика