Upload
viola
View
52
Download
0
Embed Size (px)
DESCRIPTION
Интерфейс передачи сообщений : MPI. Базовые архитектуры. Массивно-параллельные системы (MPP) Симметричные мультипроцессорные системы (SMP) Системы с неоднородным доступом к памяти (NUMA) Кластерные системы. Массивно-параллельные системы (MPP). - PowerPoint PPT Presentation
Citation preview
Интерфейс передачи Интерфейс передачи сообщенийсообщений: MPI: MPI
Базовые архитектурыБазовые архитектуры
Массивно-параллельные системы (MPP)
Симметричные мультипроцессорные системы (SMP)
Системы с неоднородным доступом к памяти (NUMA)
Кластерные системы
Массивно-параллельные системы (MPP)Массивно-параллельные системы (MPP)
MPP состоят из однородных вычислительных узлов, включающих один или несколько процессоров локальную память коммуникационный процессор или сетевой
адаптер жесткие диски и/или другие устройства
ввода/вывода (иногда)
Управление массивно-Управление массивно-параллельными системамипараллельными системами
1) На каждом узле может работать полноценная, UNIX-подобная операционная система, функционирующая отдельно от других узлов
2) Полноценная ОС работает только на управляющей машине, на каждом узле работает сильно урезанный вариант ОС, обеспечивающий работу соответствующей ветви параллельного приложения
Схема Схема MPP MPP системысистемы
ВУ №1
ВУ№...
ВУ №2
ВУ№M
ВУ№N
ВУ№..
Управляющий узел(ы)
Ввод-вывод
…
………
…
…… …………
Симметричные мультипроцессорные Симметричные мультипроцессорные системысистемы (SMP) (SMP)
Общая память
Высокоскоростная среда передачи данных
CPU CPU CPU CPUCPU
Системы с неоднородным Системы с неоднородным доступом к памятидоступом к памяти (NUMA) (NUMA)
Вы
сокоскоростной ком
мутатор
CPU CPU CPU Память
CPU CPU CPU Память
CPU CPU CPU Память
……
Кластерные системыКластерные системы
Узел (ВМ)
Высокоскоростная сеть
Узел (ВМ) Узел (ВМ)…
Этапы создания параллельной Этапы создания параллельной программыпрограммы
последовательный алгоритм подвергается распараллеливанию
вводятся две дополнительных нематематических операции: прием и передача данных
распараллеленный алгоритм записывается в виде программы, в которой операции приема и передачи записываются в терминах конкретной системы связи между ветвями
Система связиСистема связи
Система связи включает два компонента:ПрограммныйАппаратный
Способы передачи данных:Через разделяемую памятьВ виде сообщений
Краткая характеристика Краткая характеристика MPIMPI
Single program/Multiple data (SPMD)
Multiple instruction/Multiple data (MIMD)
Коммуникаторы, группы и Коммуникаторы, группы и области связиобласти связи
Группа (MPI_Group)
Область связи (communication domain)
Коммуникатор
Обрамляющие функции. Обрамляющие функции. Начало и завершениеНачало и завершение
Инициализация библиотеки MPI_Init( &argc, &argv )
Аварийное закрытие библиотеки MPI_Abort( описатель области связи, код
ошибки MPI )
Нормальное закрытие библиотеки MPI_Finalize()
Информационные функции: сообщают размер группы и порядковый номер вызывающей задачи int size, rank: MPI_Comm_size( MPI_COMM_WORLD, &size ) MPI_Comm_rank( MPI_COMM_WORLD, &rank )
ПримерПример: : использование использование MPI_Init, MPI_Init, MPI_Finalize, MPI_Comm_size, MPI_Finalize, MPI_Comm_size,
MPI_Comm_rankMPI_Comm_rank#include <mpi.h>
#include <stdio.h>
int main( int argc, char **argv )
{
int size, rank, i;
…
return 0;
}
int main( int argc, char **argv)int main( int argc, char **argv)MPI_Init( &argc, &argv );
MPI_Comm_size( MPI_COMM_WORLD, &size );
MPI_Comm_rank( MPI_COMM_WORLD, &rank );
if( rank==0 )
printf("Total processes count = %d\n", size );
printf("Hello! My rank in MPI_COMM_WORLD = %d\n", rank );
MPI_Barrier( MPI_COMM_WORLD );
if( rank == 0 )
for( puts ("Command line of process 0:"), i=0; i<argc;i++)
printf( "%d: \"%s\"\n", i, argv[i] );
MPI_Finalize();
int main( int argc, char **argv)int main( int argc, char **argv)MPI_Init( &argc, &argv );
MPI_Comm_size( MPI_COMM_WORLD, &size );
MPI_Comm_rank( MPI_COMM_WORLD, &rank );
if( rank==0 )
printf("Total processes count = %d\n", size );
printf("Hello! My rank in MPI_COMM_WORLD = %d\n", rank );
MPI_Barrier( MPI_COMM_WORLD );
if( rank == 0 )
for( puts ("Command line of process 0:"), i=0; i<argc;i++)
printf( "%d: \"%s\"\n", i, argv[i] );
MPI_Finalize();
int main( int argc, char **argv)int main( int argc, char **argv)MPI_Init( &argc, &argv );
MPI_Comm_size( MPI_COMM_WORLD, &size );
MPI_Comm_rank( MPI_COMM_WORLD, &rank );
if( rank==0 )
printf("Total processes count = %d\n", size );
printf("Hello! My rank in MPI_COMM_WORLD = %d\n", rank );
MPI_Barrier( MPI_COMM_WORLD );
if( rank == 0 )
for( puts ("Command line of process 0:"), i=0; i<argc;i++)
printf( "%d: \"%s\"\n", i, argv[i] );
MPI_Finalize();
int main( int argc, char **argv)int main( int argc, char **argv)MPI_Init( &argc, &argv );
MPI_Comm_size( MPI_COMM_WORLD, &size );
MPI_Comm_rank( MPI_COMM_WORLD, &rank );
if( rank==0 )
printf("Total processes count = %d\n", size );
printf("Hello! My rank in MPI_COMM_WORLD = %d\n", rank );
MPI_Barrier( MPI_COMM_WORLD );
if( rank == 0 )
for( puts ("Command line of process 0:"), i=0; i<argc;i++)
printf( "%d: \"%s\"\n", i, argv[i] );
MPI_Finalize();
int main( int argc, char **argv)int main( int argc, char **argv)MPI_Init( &argc, &argv );
MPI_Comm_size( MPI_COMM_WORLD, &size );
MPI_Comm_rank( MPI_COMM_WORLD, &rank );
if( rank==0 )
printf("Total processes count = %d\n", size );
printf("Hello! My rank in MPI_COMM_WORLD = %d\n", rank );
MPI_Barrier( MPI_COMM_WORLD );
if( rank == 0 )
for( puts ("Command line of process 0:"), i=0; i<argc;i++)
printf( "%d: \"%s\"\n", i, argv[i] );
MPI_Finalize();
int main( int argc, char **argv)int main( int argc, char **argv)MPI_Init( &argc, &argv );
MPI_Comm_size( MPI_COMM_WORLD, &size );
MPI_Comm_rank( MPI_COMM_WORLD, &rank );
if( rank==0 )
printf("Total processes count = %d\n", size );
printf("Hello! My rank in MPI_COMM_WORLD = %d\n", rank );
MPI_Barrier( MPI_COMM_WORLD );
if( rank == 0 )
for( puts ("Command line of process 0:"), i=0; i<argc;i++)
printf( "%d: \"%s\"\n", i, argv[i] );
MPI_Finalize();
Функции пересылки данныхФункции пересылки данныхспособ зацепления процессов автоматический выбор одного из трех вариантов: буферизация на передающей стороне ожидание на приемной стороне ожидание на передающей стороне
способ взаимодействия коммуникационного модуля MPI с вызывающим процессом: блокирующий неблокирующий
в отдельные функции выделены: создание "канала" для приема/передачи сообщения инициация приема/передачи закрытие канала
Функции Функции MPIMPI
MPI_Recv и MPI_Send – выполняют блокирующую приемопередачу с автоматическим выбором зацепления
Функции коллективных коммуникаций: broadcast – один-всем scatter – один-каждому gather – каждый-одному allgather – все-каждому alltoall – каждый-каждому
Связь Связь ““точка-точкаточка-точка””. . Простейший набор. Пример.Простейший набор. Пример.
Аргументы функций:Адрес буфера Размер буфера Тип ячейки буфера Номер задачи Идентификатор
сообщения Описатель области связи Статус завершения
приема
Задача 1 передает: int buf[10]; MPI_Send( buf, 5, MPI_INT, 1, 0, MPI_COMM_WORLD ); Задача 2 принимает: int buf[10]; MPI_Status status; MPI_Recv( buf, 10, MPI_INT, 0, 0, MPI_COMM_WORLD, &status );
Коллективные функцииКоллективные функции
Точки синхронизации, или барьеры
Функции коллективного обмена данными
Функции поддержки распределенных операций
Основные особенности и отличия от Основные особенности и отличия от коммуникаций типа коммуникаций типа ““точка-точкаточка-точка””
на прием и/или передачу работают одновременно все задачи-абоненты указываемого коммуникатора коллективная функция выполняет одновременно и прием, и передачу как правило, значения ВСЕХ параметров должны быть идентичными во всех задачах MPI назначает идентификатор для сообщений автоматически
ФункцииФункции
MPI_Bcast MPI_Bcast( buf, count, dataType,
rootRank, communicator )
MPI_Gather (MPI_Gatherv)
MPI_Scatter (MPI_Scatterv)
MPI_Allgather (MPI_Allgatherv)
MPI_Alltoall (MPI_Alltoallv)
Точки синхронизации, или Точки синхронизации, или барьерыбарьеры
int MPI_Barrier( MPI_Comm comm )
0 xxxx....xxxxxxxxxxxxxxxxxxxx 1 xxxxxxxxxxxx....xxxxxxxxxxxx 2 xxxxxxxxxxxxxxxxxxxxxx....xx
0 xxxx....xx(xxxxxxxx(||||xxxxxxxx(||xx 1 xxxxxx(||||x....xxxxxxx(xxxxxxxx(||xx 2 xxxxxx(||||xxxxxxxx(||||..xxxxxxxx(xx
время
Без барьеров:
С барьерами:
Обозначения: x нормальное выполнение . ветвь простаивает ( вызван MPI_Barrier | MPI_Barrier ждет своего вызова в остальных ветвях
Распределенные операцииРаспределенные операции
int vector[16];
int resultVector[16];
MPI_Comm_rank( MPI_COMM_WORLD, &myRank );
for( i=0; i<16; i++ )
vector[i] = myRank*100 + i;
MPI_Reduce( vector, resultVector, 16, MPI_INT, MPI_SUM, 0,
MPI_COMM_WORLD );
if( myRank==0 )
/* печатаем resultVector, равный сумме векторов */
Распределенные операцииРаспределенные операции
int vector[16];
int resultVector[16];
MPI_Comm_rank( MPI_COMM_WORLD, &myRank );
for( i=0; i<16; i++ )
vector[i] = myRank*100 + i;
MPI_Reduce( vector, resultVector, 16, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD );
if( myRank==0 )
/* печатаем resultVector, равный сумме векторов */
Распределенные операцииРаспределенные операции
int vector[16];
int resultVector[16];
MPI_Comm_rank( MPI_COMM_WORLD, &myRank );
for( i=0; i<16; i++ )
vector[i] = myRank*100 + i;
MPI_Reduce( vector, resultVector, 16, MPI_INT, MPI_SUM, 0,
MPI_COMM_WORLD );
if( myRank==0 )
/* печатаем resultVector, равный сумме векторов */
Распределенные операцииРаспределенные операции
int vector[16];
int resultVector[16];
MPI_Comm_rank( MPI_COMM_WORLD, &myRank );
for( i=0; i<16; i++ )
vector[i] = myRank*100 + i;
MPI_Reduce( vector, resultVector, 16, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD );
if( myRank==0 )
/* печатаем resultVector, равный сумме векторов */
Распределенные операцииРаспределенные операции
int vector[16];
int resultVector[16];
MPI_Comm_rank( MPI_COMM_WORLD, &myRank );
for( i=0; i<16; i++ )
vector[i] = myRank*100 + i;
MPI_Reduce( vector, resultVector, 16, MPI_INT, MPI_SUM, 0,
MPI_COMM_WORLD );
if( myRank==0 )
/* печатаем resultVector, равный сумме векторов */
Распределенные операцииРаспределенные операции
int vector[16];
int resultVector[16];
MPI_Comm_rank( MPI_COMM_WORLD, &myRank );
for( i=0; i<16; i++ )
vector[i] = myRank*100 + i;
MPI_Reduce( vector, resultVector, 16, MPI_INT, MPI_SUM, 0,
MPI_COMM_WORLD );
if( myRank==0 )
/* печатаем resultVector, равный сумме векторов */
Распределенные операцииРаспределенные операции
int vector[16];
int resultVector[16];
MPI_Comm_rank( MPI_COMM_WORLD, &myRank );
for( i=0; i<16; i++ )
vector[i] = myRank*100 + i;
MPI_Reduce( vector, resultVector, 16, MPI_INT, MPI_SUM, 0,
MPI_COMM_WORLD );
if( myRank==0 )
/* печатаем resultVector, равный сумме векторов */
Распределенные операцииРаспределенные операции
int vector[16];
int resultVector[16];
MPI_Comm_rank( MPI_COMM_WORLD, &myRank );
for( i=0; i<16; i++ )
vector[i] = myRank*100 + i;
MPI_Reduce( vector, resultVector, 16, MPI_INT, MPI_SUM, 0,
MPI_COMM_WORLD );
if( myRank==0 )
/* печатаем resultVector, равный сумме векторов */
Распределенные операцииРаспределенные операции
int vector[16];
int resultVector[16];
MPI_Comm_rank( MPI_COMM_WORLD, &myRank );
for( i=0; i<16; i++ )
vector[i] = myRank*100 + i;
MPI_Reduce( vector, resultVector, 16, MPI_INT, MPI_SUM, 0,
MPI_COMM_WORLD );
if( myRank==0 )
/* печатаем resultVector, равный сумме векторов */
Предопределенные описатели Предопределенные описатели операций в операций в MPIMPI
MPI_MAX и MPI_MIN ищут поэлементные максимум и минимум; MPI_SUM вычисляет сумму векторов; MPI_PROD вычисляет поэлементное произведение векторов; MPI_LAND, MPI_BAND, MPI_LOR, MPI_BOR, MPI_LXOR, MPI_BXOR - логические и двоичные операции И, ИЛИ, исключающее ИЛИ; MPI_MAXLOC, MPI_MINLOC - поиск индексированного минимума/максимума.
ОперацииОперации
Ассоциативные: (a+b)+c = a+(b+c)
Коммутативные: a+b = b+a
Операции:MPI_Allreduce MPI_Reduce_scatter MPI_Scan
Создание коммутаторов и группСоздание коммутаторов и группКопирование:MPI_Comm tempComm; MPI_Comm_dup( MPI_COMM_WORLD, &tempComm ); MPI_Comm_free( &tempComm );
Расщепление:
MPI_Comm_split( existingComm, indexOfNewSubComm, rankInNewSubComm, &newSubComm );
Создание через группы: MPI_Comm_group MPI_Group_xxx MPI_Comm_create MPI_Group_free
MPI MPI и типы данныхи типы данныхВсе функции приемопередачи в MPI оперируют не количеством передаваемых байт, а количеством ячеек
В MPI имеется механизм конструирования пользовательских описателей на базе уже имеющихся (как пользовательских, так и встроенных)
При создании в MPI сняты ограничения:Ячейки не налезают друг на друга Ячейки не располагаются с разрывами
Зачем Зачем MPI MPI знать тип знать тип передаваемых данныхпередаваемых данных
Пользовательские типы данных
Приложение MPI может работать на гетерогенном вычислительном комплексе (коллективе ЭВМ с разной архитектурой)
Фортрановский тип CHARACTER
Структуры в Си
Использование Использование MPIMPI
Средства автоматической декомпозиции
Языки программирования
Оптимизированные библиотеки для стандартных языков
Средства визуального проектирования
Отладчики
MPI-1 MPI-1 и и MPI-2MPI-2
Нововведения в MPI-2:Взаимодействие между приложениями.
Поддержка механизма "клиент-сервер". Динамическое порождение ветвей Для работы с файлами создан архитектурно-
независимый интерфейс Разделяемая память может быть не только
каналом связи между ветвями, но и местом совместного хранения данных
#include <mpi.h>
#include <stdio.h>
#define tagFloatData 1
#define tagDoubleData 2
#define ELEMS(x) ( sizeof(x) / sizeof(x[0]) )
ПримерПример
#include <mpi.h>
#include <stdio.h>
#define tagFloatData 1
#define tagDoubleData 2
#define ELEMS(x) ( sizeof(x) / sizeof(x[0]) )
ПримерПример
#include <mpi.h>
#include <stdio.h>
#define tagFloatData 1
#define tagDoubleData 2
#define ELEMS(x) ( sizeof(x) / sizeof(x[0]) )
ПримерПример
int main( int argc, char **argv )
{
int size, rank, count;
float floatData[10];
double doubleData[20];
MPI_Status status;
MPI_Init( &argc, &argv );
MPI_Comm_size( MPI_COMM_WORLD, &size );
MPI_Comm_rank( MPI_COMM_WORLD, &rank );
ПримерПример
if (size != 2) {
if (rank == 0)
printf("Error: two processes required instead of %d, abort\n", size );
MPI_Barrier( MPI_COMM_WORLD );
MPI_Abort(MPI_COMM_WORLD, MPI_ERR_OTHER);
return -1;
}
ПримерПример
if (size != 2) {
if (rank == 0)
printf("Error: two processes required instead of %d, abort\n", size );
MPI_Barrier( MPI_COMM_WORLD );
MPI_Abort(MPI_COMM_WORLD, MPI_ERR_OTHER);
return -1;
}
ПримерПример
if (size != 2) {
if (rank == 0)
printf("Error: two processes required instead of %d, abort\n", size );
MPI_Barrier( MPI_COMM_WORLD );
MPI_Abort(MPI_COMM_WORLD, MPI_ERR_OTHER);
return -1;
}
ПримерПример
if (rank == 0) {
MPI_Send(floatData, 5, MPI_FLOAT, 1, tagFloatData, MPI_COMM_WORLD);
ПримерПример
if (rank == 0) {
MPI_Send(floatData, 5, MPI_FLOAT, 1, tagFloatData, MPI_COMM_WORLD);
ПримерПример
if (rank == 0) {
MPI_Send(floatData, 5, MPI_FLOAT, 1, tagFloatData, MPI_COMM_WORLD);
ПримерПример
if (rank == 0) {
MPI_Send(floatData, 5, MPI_FLOAT, 1, tagFloatData, MPI_COMM_WORLD);
ПримерПример
if (rank == 0) {
MPI_Send(floatData, 5, MPI_FLOAT, 1, tagFloatData, MPI_COMM_WORLD);
ПримерПример
if (rank == 0) {
MPI_Send(floatData, 5, MPI_FLOAT, 1, tagFloatData, MPI_COMM_WORLD);
ПримерПример
if (rank == 0) {
MPI_Send(floatData, 5, MPI_FLOAT, 1, tagFloatData, MPI_COMM_WORLD);
ПримерПример
MPI_Send(doubleData, 6, MPI_DOUBLE, 1, tagDoubleData,
MPI_COMM_WORLD);
} else {
MPI_Recv(doubleData, ELEMS(doubleData), MPI_DOUBLE, 0, tagDoubleData, MPI_COMM_WORLD, &status);
ПримерПример if (rank == 0) {
MPI_Send(floatData, 5, MPI_FLOAT, 1, tagFloatData, MPI_COMM_WORLD);
MPI_Send(doubleData, 6, MPI_DOUBLE, 1, tagDoubleData,
MPI_COMM_WORLD);
} else {
MPI_Recv(doubleData, ELEMS(doubleData), MPI_DOUBLE, 0, tagDoubleData, MPI_COMM_WORLD, &status);
ПримерПример if (rank == 0) {
MPI_Send(floatData, 5, MPI_FLOAT, 1, tagFloatData, MPI_COMM_WORLD);
MPI_Send(doubleData, 6, MPI_DOUBLE, 1, tagDoubleData,
MPI_COMM_WORLD);
} else {
MPI_Recv(doubleData, ELEMS(doubleData), MPI_DOUBLE, 0, tagDoubleData, MPI_COMM_WORLD, &status);
ПримерПример if (rank == 0) {
MPI_Send(floatData, 5, MPI_FLOAT, 1, tagFloatData, MPI_COMM_WORLD);
MPI_Send(doubleData, 6, MPI_DOUBLE, 1, tagDoubleData,
MPI_COMM_WORLD);
} else {
MPI_Recv(doubleData, ELEMS(doubleData), MPI_DOUBLE, 0, tagDoubleData, MPI_COMM_WORLD, &status);
ПримерПример if (rank == 0) {
MPI_Send(floatData, 5, MPI_FLOAT, 1, tagFloatData, MPI_COMM_WORLD);
MPI_Send(doubleData, 6, MPI_DOUBLE, 1, tagDoubleData,
MPI_COMM_WORLD);
} else {
MPI_Recv(doubleData, ELEMS(doubleData), MPI_DOUBLE, 0, tagDoubleData, MPI_COMM_WORLD, &status);
ПримерПример if (rank == 0) {
MPI_Send(floatData, 5, MPI_FLOAT, 1, tagFloatData, MPI_COMM_WORLD);
MPI_Send(doubleData, 6, MPI_DOUBLE, 1, tagDoubleData,
MPI_COMM_WORLD);
} else {
MPI_Recv(doubleData, ELEMS(doubleData), MPI_DOUBLE, 0, tagDoubleData, MPI_COMM_WORLD, &status);
ПримерПример if (rank == 0) {
MPI_Send(floatData, 5, MPI_FLOAT, 1, tagFloatData, MPI_COMM_WORLD);
MPI_Send(doubleData, 6, MPI_DOUBLE, 1, tagDoubleData,
MPI_COMM_WORLD);
} else {
MPI_Recv(doubleData, ELEMS(doubleData), MPI_DOUBLE, 0, tagDoubleData, MPI_COMM_WORLD, &status);
ПримерПример if (rank == 0) {
MPI_Send(floatData, 5, MPI_FLOAT, 1, tagFloatData, MPI_COMM_WORLD);
MPI_Send(doubleData, 6, MPI_DOUBLE, 1, tagDoubleData,
MPI_COMM_WORLD);
} else {
MPI_Recv(doubleData, ELEMS(doubleData), MPI_DOUBLE, 0, tagDoubleData, MPI_COMM_WORLD, &status);
ПримерПример if (rank == 0) {
MPI_Send(floatData, 5, MPI_FLOAT, 1, tagFloatData, MPI_COMM_WORLD);
MPI_Get_count(&status, MPI_DOUBLE, &count);
ПримерПример if (rank == 0) {
MPI_Send(floatData, 5, MPI_FLOAT, 1, tagFloatData, MPI_COMM_WORLD);
MPI_Send(doubleData, 6, MPI_DOUBLE, 1, tagDoubleData,
MPI_COMM_WORLD);
} else {
MPI_Recv(doubleData, ELEMS(doubleData), MPI_DOUBLE, 0, tagDoubleData, MPI_COMM_WORLD, &status);
MPI_Get_count(&status, MPI_DOUBLE, &count);
ПримерПример if (rank == 0) {
MPI_Send(floatData, 5, MPI_FLOAT, 1, tagFloatData, MPI_COMM_WORLD);
MPI_Send(doubleData, 6, MPI_DOUBLE, 1, tagDoubleData,
MPI_COMM_WORLD);
} else {
MPI_Recv(doubleData, ELEMS(doubleData), MPI_DOUBLE, 0, tagDoubleData, MPI_COMM_WORLD, &status);
MPI_Get_count(&status, MPI_DOUBLE, &count);
ПримерПример if (rank == 0) {
MPI_Send(floatData, 5, MPI_FLOAT, 1, tagFloatData, MPI_COMM_WORLD);
MPI_Send(doubleData, 6, MPI_DOUBLE, 1, tagDoubleData,
MPI_COMM_WORLD);
} else {
MPI_Recv(doubleData, ELEMS(doubleData), MPI_DOUBLE, 0, tagDoubleData, MPI_COMM_WORLD, &status);
MPI_Get_count(&status, MPI_DOUBLE, &count);
ПримерПример if (rank == 0) {
MPI_Send(floatData, 5, MPI_FLOAT, 1, tagFloatData, MPI_COMM_WORLD);
MPI_Send(doubleData, 6, MPI_DOUBLE, 1, tagDoubleData,
MPI_COMM_WORLD);
} else {
MPI_Recv(doubleData, ELEMS(doubleData), MPI_DOUBLE, 0, tagDoubleData, MPI_COMM_WORLD, &status);
printf("Received %d elems\n", count);
ПримерПример if (rank == 0) {
MPI_Send(floatData, 5, MPI_FLOAT, 1, tagFloatData, MPI_COMM_WORLD);
MPI_Send(doubleData, 6, MPI_DOUBLE, 1, tagDoubleData,
MPI_COMM_WORLD);
} else {
MPI_Recv(doubleData, ELEMS(doubleData), MPI_DOUBLE, 0, tagDoubleData, MPI_COMM_WORLD, &status);
MPI_Get_count(&status, MPI_DOUBLE, &count);
MPI_Recv(floatData, ELEMS(floatData), MPI_FLOAT, 0, tagFloatData, MPI_COMM_WORLD, &status);
MPI_Get_count(&status, MPI_FLOAT, &count);
}
MPI_Finalize();
return 0;
}
ПримерПример
Коллективные функцииКоллективные функции
A0
broadcast
A0
A0
A0
A0
A0
A0
Коллективные функцииКоллективные функции
A0 A1 A2 A3 A4 A5 A0
A1
A2
A3
A4
A5
scatter
gather
Коллективные функцииКоллективные функции
A0
B0
C0
D0
E0
F0
allgather
A0
A0
A0
A0
A0
A0
B0
B0
B0
B0
B0
B0
C0
C0
C0
C0
C0
C0
D0
D0
D0
D0
D0
D0
E0
E0
E0
E0
E0
E0
F0
F0
F0
F0
F0
F0
Коллективные функцииКоллективные функции
A0 A1 A2 A3 A4 A5
B0 B1 B2 B3 B4 B5
C0 C1 C2 C3 C4 C5
D0 D1 D2 D3 D4 D5
E0 E1 E2 E3 E4 E5
F0 F1 F2 F3 F4 F5
A0
A1
A2
A3
A4
A5
B0
B1
B2
B3
B4
B5
C0 D0 E0 F0
C1
C2
C3
C4
C5
D1
D2
D3
D4
D5
E1
E2
E3
E4
E5
F1
F2
F3
F4
F5
alltoall
Общие функцииОбщие функции
int MPI_Init( int* argc, char*** argv)int MPI_Finalize( void )
int MPI_Comm_size( MPI_Comm comm, int* size)int MPI_Comm_rank( MPI_comm comm, int* rank)
double MPI_Wtime(void)
int MPI_Barrier( MPI_Comm comm)
Прием-передача-базовыеПрием-передача-базовыеint MPI_{I}Send(void* buf, int count, MPI_Datatype datatype, int dest, int msgtag, MPI_Comm comm{, MPI_Request *request})
int MPI_{I}Recv(void* buf, int count, MPI_Datatype datatype, int source, int msgtag, MPI_comm comm, MPI_Status *status{, MPI_Request *request})
int MPI_Probe( int source, int msgtag, MPI_Comm comm, MPI_Status *status)
int MPI_Get_Count( MPI_Status *status, MPI_Datatype datatype, int *count)
Асинхронные прием-передачаАсинхронные прием-передача:: действия с квитанциямидействия с квитанциями
int MPI_Wait( MPI_Request *request, MPI_Status *status)
int MPI_WaitAll( int count, MPI_Request *requests, MPI_Status *statuses)
int MPI_WaitAny( int count, MPI_Request *requests, int *index, MPI_Status *status)
int MPI_WaitSome( int incount, MPI_Request *requests, int *outcount, int *indexes, MPI_Status *statuses)
Асинхронные прием-передачаАсинхронные прием-передача:: действия с квитанциямидействия с квитанциями
int MPI_Test( MPI_Request *request, int *flag, MPI_Status *status)
int MPI_TestAll( int count, MPI_Request *requests, int *flag, MPI_STatus *statuses)
int MPI_TestAny(int count, MPI_Request *requests, int *index, int *flag, MPI_Status *status)
int MPI_TestSome( int incount, MPI_Request *requests, int *outcount, int *indexes, MPI_Status *statuses)
Объединение запросовОбъединение запросов
int MPI_Send_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)
MPI_Start_All( int count, MPI_Request *requests)