Вы находитесь на странице: 1из 4

ТЕХНОЛОГИЯ ПАРАЛЛЕЛЬНОГО ПРОГРАММИРОВАНИЯ MPI

Лекция 4. Типы данных. Пользовательские типы.

На практике нередко требуется осуществить передачу данных, расположенных не в


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

Производные типы
Производные типы данных создаются при выполнении программы на базе существующих
на текущий момент базовых и производных типов данных. Создание типа данных происходит в
два этапа: конструирование типа, затем его регистрация. После регистрации производный тип
можно использовать в операциях обмена данными, в том числе и в коллективных операциях.
После завершения работы с типом его рекомендуется уничтожить.
Производный тип – это по сути шаблон (маска), который задает последовательность
выборки данных из ячеек памяти. Производный тип представляет собой последовательность
базовых (производных) типов и соответствующим ей набором смещений каждого типа
относительно некоторой заданной точки.
Характеристики производного типа:
Typemap = {(type_0;disp_0), (type_1;disp_1),…,(type_N;disp_N) } – карта типа;
lb(Typemap) = min disp_j – минимальное смещение относительно заданной точки – нижняя
граница элемента типа;
ub(Typemap) = max (disp_j+sizeof(type_j))+e – верхняя граница элемента типа –
максимальное смещение относительно заданной точки;
extent(Typemap) = ub(Typemap) - lb(Typemap) – величина диапазона между верхней и
нижней границами типа (ширина типа).

Конструкторы типов:
1) Создание нового типа как определенного кол-ва последовательно расположенных
элементов базового типа.
int MPI_Type_contiguous (int count, MPI_Datatype oldtype, MPI_Datatype *newtype);
Oldtype: Typemap = {(type_0;disp_0),…,(type_N;disp_N) }
Newtype: Typemap = {(type_0;disp_0),…,(type_N;disp_N),
(type_0;disp_0 + extent),…,(type_N;disp_N+extent),… }

MPI_Type_contiguous (10, MPI_INT, &newtype);

Typemap(oldtype)={(double;0), (char;8)}
Extent(oldtype)=16
MPI_Type_contiguous (3, oldtype, &newtype);
Typemap(newtype)={(double;0), (char;8), (double;16), (char;24), (double;32), (char;40)}

1
2) Создание нового типа из блоков базового типа
int MPI_Type_vector (int count, int blocklength, int stride, MPI_Datatype oldtype,
MPI_Datatype *newtype);
Функция создает новый тип как count блоков по blocklength элементов базового типа,
каждый следующий блок начинается через stride элементов базового типа от начала
предыдущего блока (первой компоненты типа первого элемента блока).
Oldtype: Typemap = {(type_0;disp_0),…,(type_N;disp_N) }
Newtype: Typemap =
{(type_0;disp_0),…,(type_N;disp_N),
(type_0;disp_0 + extent),…,(type_N;disp_N+extent),
…….
(type_0;disp_0 + (bl-1)*extent),…,(type_N;disp_N+(bl-1)*extent),
{(type_0;disp_0 + stride*extent),…,(type_N;disp_N + stride*extent),
(type_0;disp_0 + (stride+1)*extent),…,(type_N;disp_N+(stride+1)*extent),
…….
(type_0;disp_0 + (stride+bl-1)*extent),…,(type_N;disp_N+(stride+bl-1)*extent),
……..

MPI_Type_vector (4, 2, 3, MPI_FLOAT, &newtype);

3) Создание нового типа из блоков базового типа (модификация)


int MPI_Type_hvector (int count, int blocklength, MPI_Aint stride, MPI_Datatype oldtype,
MPI_Datatype *newtype);
Функция создает новый тип как count блоков по blocklength элементов базового типа,
каждый следующий блок начинается через stride байт от начала предыдущего блока.

4) Создание нового типа из блоков базового типа переменной длины


int MPI_Type_indexed (int count, int *array_of_blocklength, int *array_of_displacement,
MPI_Datatype oldtype, MPI_Datatype *newtype);
Функция создает новый тип как count блоков элементов базового типа, i-й блок состоит
из array_of_blocklength[i] элементов, каждый следующий блок идет со смещением на
array_of_displacement[i] элементов базового типа от начала disp_0 первой компоненты
типа

MPI_Type_indexed (4, {3,1,2,4}, {0,1,5,8}, MPI_DOUBLE, &newtype);

5) Создание нового типа из блоков базового типа переменной длины (модификация)


int MPI_Type_hindexed (int count, int *array_of_blocklength, MPI_Aint
*array_of_displacement, MPI_Datatype oldtype, MPI_Datatype *newtype);
Функция создает новый тип как count блоков элементов базового типа, i-й блок состоит
из array_of_blocklength[i] элементов, каждый следующий блок идет со смещением на
array_of_displacement[i] байт от начала disp_0 первой компоненты базового типа.

6) Создание нового типа на базе нескольких типов

2
int MPI_Type_struct (int count, int *array_of_blocklength, int *array_of_displacement,
MPI_Datatype *array_of_types, MPI_Datatype *newtype);
Функция создает новый тип как count блоков элементов базового типа, i-й блок состоит
из array_of_blocklength[i] элементов типа array_of_types[i], каждый следующий блок
идет со смещением на array_of_displacement[i] байт от начала disp_0 первой
компоненты типа array_of_types[i].

struct st{
int a;
double b;
char c[50];
}
MPI_Type_struct (3, {1,1,50}, {0,4,12}, {MPI_INT, MPI_DOUBLE, MPI_CHAR},
&newtype);

Регистрация типа
int MPI_Type_commit (MPI_Datatype *datatype);

Аннулирование (удаление) типа


int MPI_Type_free (MPI_Datatype *datatype);
Функция помечает объект datatype к удалению и устанавливает datatype в
MPI_DATATYPE_NULL.

Определение параметров типа:


int MPI_Type_size (MPI_Datatype datatype, int *size);
int MPI_Type_extent (MPI_Datatype datatype, MPI_Aint *extent);
int MPI_Type_lb (MPI_Datatype datatype, MPI_Aint *disp);
int MPI_Type_ub (MPI_Datatype datatype, MPI_Aint *disp);
int MPI_Type_create_resized (MPI_Datatype datatype, MPI_Aint lb, MPI_Aint extent,
MPI_Datatype datatype *newtype);

Определение адреса
int MPI_Address (void *location, MPI_Aint *address);

Упаковка данных
Для пересылки разнородных типов данных можно использовать механизм упаковки
данных. Разнородные данные, находящиеся в разных местах памяти упаковываются в один
буфер, пересылаются и распаковываются на принимающей стороне. При передаче данных
указывается тип MPI_PACKED.

int MPI_Pack (void *inbuf, int incount, MPI_Datatype datatype, void *outbuf, int outsize, int
*position, MPI_Comm comm);

3
Функция пакует incount данных типа datatype, начиная с адреса inbuf в буфер outbuf
размера outsize, начиная с позиции position. Значение position увеличивается на кол-во
запакованных байт.

int MPI_Unpack (void *inbuf, int insize, int *position, void *outbuf, int outcount, MPI_Datatype
datatype, MPI_Comm comm);
Функция обратная к MPI_Pack.

int MPI_Pack_size ( int incount, MPI_Datatype datatype, MPI_Comm comm., int *size);
Функция определяет размер памяти в байтах, необходимых для запаковки incount
элементов типа datatype. Необходимый для паковки размер может превышать суммарный размер
данных.