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

Содержание

Слайд 2

План MPI PVM

План

MPI
PVM

Слайд 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.html
http://www.cluster.kiev.ua/support/documentation/
http://www.cluster.kiev.ua/support/documentation/pvm3/book/pvm-book.html

Слайд 4

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

Интерфейсы разработки параллельных программ

API для распределенного программирования не рассчитаны на разработку

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

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

Стандарт MPI

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

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

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

Основные понятия

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

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

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

Запуск MPI машины

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

LAMRSH="rsh“
Виртуальная машина запускается командой
lamboot <файл списка машин>
Первой в списке должна быть локальная машина
node1
node2
Слайд 8

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

Запуск программ

mpirun –np <количество процессоров> <программа>

Слайд 9

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

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

Все процессы чаще всего выполняют один и тот же

исполняемый файл
Первой MPI функцией должна быть вызвана
MPI_Init( &argc, &argv )
Последней одна из функций
MPI_Finalize() - нормальное завершение
MPI_Abort( описатель области связи, код ошибки 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
Слайд 11

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

Пример 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;
}
Слайд 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;

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

#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;
}
Слайд 16

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

Компиляция и выполнения

[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
Слайд 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<5; i++) ranks[i]=i;
MPI_Group_excl(group,5,ranks,&subgroup);
Слайд 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[]){

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

#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;
}
Слайд 22

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

Компиляция и выполнение

[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
Слайд 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,

Операции точка-точка (блокирующие)

Передача
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
Коммуникатор в каком передавать
Результат операции (только для приема)
Слайд 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_Broadcast
MPI_Reduce
MPI_Gather
MPI_Scatter
MPI_All_Gather

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

Слайд 28

#include "mpi.h" int main(int argc, char* argv[]){ MPI_Comm subComm; int size,

#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<16; 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;
}
Слайд 29

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

Пример выполнения

[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
Слайд 30

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

Типы данных

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

при передаче преобразовывать представления данных (XDR)
Для каждого типа своя функция преобразования
Можно создавать свои типы данных, которые тоже будут передаваться корректно
Слайд 31

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

Встроенные типы данных

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

Слайд 32

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

Создание новых типов данных

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

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

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

Функции создания новых типов данных

MPI_Type_struct( count, /* количество полей */ int

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

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

Пример создания типа структуры

#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, ... );
Слайд 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)
Слайд 36

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

Распаковка данных

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)
Слайд 37

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

Пример упаковки-распаковки

#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);
Слайд 38

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

Асинхронные операции

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

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

Функции асинхронной передачи-приема MPI_Isend (&buf,count,datatype,dest,tag,comm,&request) MPI_Irecv (&buf,count,datatype,source,tag,comm,&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_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)
Слайд 41

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

Пример асинхронной операции

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);
Слайд 42

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

Расширенные возможности MPI-2

Параллельный ввод-вывод в разные части файла
Доступ к памяти на

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

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
При этом запускается демон на локальной

машине
Запуск программ на других машинах выполняется через команду $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
Слайд 46

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

Функции управления процессами

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

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

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

Функции управления процессами

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

завершение своего процесса
Слайд 48

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

Управление виртуальной машиной

Добавление физических машин
int info = pvm_addhosts( char **hosts, int

nhost, int *infos )
Удаление физических машин
int info = pvm_delhosts( char **hosts, int nhost, int *infos )
Остановка виртуальной машины
pvm_halt()
Слайд 49

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

Пример

#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;
}
Слайд 50

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

Пример выполнения и компиляции

[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
Слайд 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

Отправка-прием

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

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

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

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

#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;
}
Слайд 56

Пример выполнения [saa@cluster pvm]$ gcc ./msg.c -I$PVM_ROOT/include -L$PVM_ROOT/lib/$PVM_ARCH -lpvm3 -o msg

Пример выполнения

[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