Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции_MPI_OpenMP.doc
Скачиваний:
15
Добавлен:
16.11.2019
Размер:
1.09 Mб
Скачать

6. Структурный

MPI_Type_struct общий конструктор: он обобщает предыдущий конструктор таким образом, что позволяет каждому блоку состоять из различных типов данных.

MPI_Type_struct (count, array_of_blocklengths, array_of_displacements, array_of_types, newtype)

IN

count

количество блоков (int)

IN

array_of_blocklengths

число элем-ов в каждом блоке (массив int длиной count)

IN

array_of_displacements

смещение каждого блока в байтах (массив int длиной count)

IN

array_of_types

тип элемента в каждом блоке (массив типов длиной count)

OUT

newtype

новый тип данных (handle)

Пример Пусть type1 имеет карту типа {(double, 0), (char, 8)}, с протяжённостью 16. Пусть B=(2,1,3), D=(0,16,26), и T=(MPI_FLOAT, type1, MPI_CHAR). Тогда вызов MPI_TYPE_STRUCT(3, B, D, T, newtype) создает тип данных с картой,

{(float,0), (float,4), (double,16), (char,24), (char,26), (char,27), (char,28)}:

две копии MPI_FLOAT начинаются с 0, затем копия типа type1 начинается с 16, далее идут три копии MPI_CHAR, начинающиеся с 26.

Пример. Копирование нижней треугольной части матрицы. Для создания нового типа данных используем MPI_Type_indexed

#include <mpi.h>

#include <iostream.h>

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

int a[8][8], b[8][8];

int disp[8], block[8];

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

MPI_Status stat;

for(i=0; i<8; i++){

for(int j=0; j<8; j++){

a[i][j]= (j<=i)?(i+1):0;

cout<<a[i][j]<<"\t";

}

cout<<endl;

}

// копирует нижнюю треугольную часть матрицы a в нижнюю треугольную часть

// матрицы b

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

// вычисляет начало и размер каждого блока (блок – это строка матрицы)

disp[0] = 0;

block[0] = 1;

for (i=1; i<8; i++){

disp[i] = 8*i;

block[i] = i+1;

}

// создание типа данных для нижней треугольной части матрицы, далее этот тип

// данных можно использовать в обменах

MPI_Datatype my_type; //объявили имя нового типа данных

MPI_Type_indexed(count, block, disp, MPI_INT, &my_type);

MPI_Type_commit(&my_type); //зафиксировали новый тип данных

if(rank==0)

MPI_Send(a, 1, my_type, 1, 99, MPI_COMM_WORLD);

if(rank==1){

MPI_Recv(b, 1, my_type, 0, 99, MPI_COMM_WORLD, &stat);

cout<<endl<<"RESULT MATRIX"<<endl;

for(i=0; i<8; i++){

for(int j=0; j<8; j++){

cout<<((j<=i)?b[i][j]:0)<<"\t";

}

cout<<endl;

}

}

MPI_Finalize();

}

Лекция 6

Адресные функции и функции экстентов. Конструкторы групп и коммуникаторов. Интракоммуникаторы.

Функция MPI_Address возвращает байтовый адрес элемента (ячейки)

MPI_Address (location, address)

IN location элемент (ячейка в памяти)

OUT address адрес ячейки (целое)

Пример Использование MPI_Address для вещественного массива.

double m[100];

MPI_Aint i1, i2, diff; // MPI_Aint – это long

MPI_Address(&m[0], &i1);

MPI_Address(&m[9], &i2);

diff = i2 – i1;

значение diff есть 9*sizeof(double) =72.

Функция MPI_Type_extent возвращает экстент (протяженность типа данных) типа данных.

MPI_Type_extent(datatype, extent)

IN datatype тип данных (дескриптор)

OUT extent экстент типа данных (целое)

Функция MPI_Type_size возвращает общий размер в байтах типа данных, указанного в datatype.

MPI_Type_size (datatype, size)

IN datatype тип данных (дескриптор)

OUT size размер типа данных (целое)

Маркеры нижней и верхней границ

Часто удобно явно указать нижнюю и верхнюю границы карты типа. Это позволяет определить тип данных, который имеет «дыры» в начале или конце, или тип с элементами, которые идут выше верхней или ниже нижней границы. Пользователь может явно описать границы типа данных, которые соответствуют этим структурам.

Псевдо тип данных: MPI_LB используется для маркировки нижней границы типа данных, MPI_UB используется для маркировки верхней границы типа данных. Маркеры границ не занимают места в памяти, их размер равен 0 (экстент (MPI_LB) = экстент (MPI_UB) =0), они не меняют size или count типа данных и не влияют на содержание сообщения, выполняемого с этим типом данных. Маркеры границ влияют на определение экстента типа данных и, следовательно, влияют на результат репликации (отображения) этого типа данных конструктором типа данных.

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

MPI_Type_lb ( datatype, displacement)

IN datatype тип данных (дескриптор)

OUT displacement смещение нижней границы от исходной в байтах (целое)

MPI_Type_ub ( datatype, displacement)

IN datatype тип данных (дескриптор)

OUT displacement смещение верхней границы от исходной в байтах (целое)

Напомню, что количество полученных в сообщении элементов можно определить функцией MPI_Get_count. Также количество полученных в сообщении элементов можно получить с помощью функции MPI_Get_elements.

MPI_Get_elements ( status, datatype, count)

IN status статус операции приема (статус)

IN datatype тип данных операции приема (дескриптор)

OUT count число принятых базисных элементов (целое)

Функция MPI_Get_elements может использоваться после операции probe, чтобы определить число элементов в сообщении. Заметим, что две функции MPI_Get_count и MPI_Get_elements возвращают то же самое значение, когда они используются с базисным типом данных.

Группы и коммуникаторы

Интерфейс MPI использует такие понятия, как группы процессов (groups), виртуальные топологии (virtual topologies) и коммуникаторы (communicators).

Коммуникаторы создают область для всех операций обмена в MPI. Коммуникаторы разделяются на два вида: интра-коммуникаторы - внутригрупповые коммуникаторы, предназначенные для операций в пределах группы процессов, и интер-коммуникаторы - межгрупповые коммуникаторы, предназначенные для обменов между двумя группами процессов. Начальный для всех процессов интра-коммуникатор MPI_COMM_WORLD, который создается сразу при обращении к функции MPI_INIT. Удалить коммуникатор MPI_COMM_WORLD нельзя. Кроме того, существует коммуникатор, который содержит только себя как процесс – MPI_COMM_SELF.

Группы определяют упорядоченную набор процессов по именам, именами процессов являются их порядковые номера. Группы определяют область для выполнения обменов, но в операциях обмена могут использоваться только коммуникаторы. Группа определена в пределах коммуникатора. В MPI определена предопределенная группа: MPI_GROUP_EMPTY – это группа без процессов.

Виртуальная топология определяет отображение номеров процессов в группе на определенную топологию, и наоборот. Для создания виртуальных топологий определены специальные конструкторы, рассматривать которые будем позже.

Управление группой

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

Функции доступа к группе

1. MPI_Group_size(MPI_Group group, int *size) позволяет определить размер группы.

IN group группа (дескриптор)

OUT size количество процессов в группе (целое)

2. MPI_Group_rank(MPI_Group group, int *rank) служит для определения номера процесса в группе.

IN group группа (дескриптор)

OUT rank номер процесса в группе или MPI_UNDEFINED, если процесс не является членом группы (целое)