- •Разработка
- •План
- •Литература
- •Интерфейсы разработки параллельных программ
- •Стандарт MPI
- •Основные понятия
- •Запуск MPI машины
- •Запуск программ
- •Структура MPI программы
- •Основной коммуникационный домен
- •Пример MPI программы
- •Создание новых коммуникационных доменов
- •Копирование доменов
- •Разбиение существующего домена на части
- •Пример расщепления
- •Компиляция и выполнения
- •Создание коммуникатора на базе группы
- •Создание группы на базе коммуникатора
- •Операции с группами
- •Создание нового коммуникатора на базе
- •Пример работы с группами
- •Компиляция и выполнение
- •Получение имени машины, где работает процесс
- •Операции передачи данных
- •Операции точка-точка (блокирующие)
- •Результат операции (статус)
- •Коллективные (распределенные) операции
- •Пример выполнения
- •Типы данных
- •Встроенные типы данных
- •Создание новых типов данных
- •Функции создания новых типов данных
- •Пример создания типа структуры
- •Упаковка данных (сериализация)
- •Распаковка данных
- •Пример упаковки- распаковки
- •Асинхронные операции
- •Функции асинхронной передачи-приема
- •Проверка состояния
- •Пример асинхронной операции
- •Расширенные возможности MPI-2
- •Параллельная машина
- •Запуск параллельной машины
- •Функции управления процессами
- •Функции управления процессами
- •Управление виртуальной машиной
- •Пример
- •Пример выполнения и компиляции
- •Прием и отправка сообщений
- •Инициализация буфера упаковки
- •Упаковка и распаковка сообщений
- •Отправка-прием
- •Пример программы
- •Пример выполнения
- •Вопросы ?
Пример работы с группами
#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;
}
Компиляция и выполнение
[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
Получение имени машины, где работает процесс
char nm[4096];
int name_size = 4096; MPI_Get_processor_name(nm, &nm_size);
Операции передачи данных
Все передачи данных выполняются в пределах коммуникатора
Данные пересылаются в виде сообщений
Сообщение имеет номер (тег)
В одном сообщении могут быть данные любой сложности
Операции передачи данных
Точка-точка
Коллективные
Broadcst
Reduce
Синхронные – блокируется пока не завершится
Асинхронные – не блокируется
Операции точка-точка (блокирующие)
Передача 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
Коммуникатор в каком передавать
Результат операции (только для приема)
Результат операции (статус)
Данные могут прийти
неизвестно от кого
С неизвестным тегом
В неизвестном количестве
При приеме может возникнуть ошибка
Определение количества данных
MPI_Status status;
int count;
MPI_Recv( ... , MPI_INT, ... , &status );
MPI_Get_count( &status, MPI_INT, &count );
/* ... теперь count содержит количество принятых ячеек */
Коллективные (распределенные) операции
MPI_Broadcast
MPI_Reduce
MPI_Gather
MPI_Scatter
MPI_All_Gather
…
Выполняются всеми процессами для эффективного выполнения суммирования, умножения …
#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;
}
Пример выполнения
[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
Типы данных
На разных аппаратных платформах одинаковые типы данных представляются по разному
Необходимо при передаче преобразовывать представления данных (XDR)
Для каждого типа своя функция преобразования
Можно создавать свои типы данных, которые тоже будут передаваться корректно