Next:5.2. Передача упакованных данных
Up:5. ПРОИЗВОДНЫЕ ТИПЫ ДАННЫХ И ПЕРЕДАЧА УПАКОВАННЫХ ДАННЫХ
Prev:5. ПРОИЗВОДНЫЕ ТИПЫ ДАННЫХ И ПЕРЕДАЧА УПАКОВАННЫХ ДАННЫХ

5.1. Производные типы данных

Производные типы MPI не являются в полном смысле типами данных, как это понимается в языках программирования. Они не могут использоваться ни в каких других операциях, кроме коммуникационных. Производные типы MPI следует понимать как описатели расположения в памяти элементов базовых типов. Производный тип MPI представляет собой скрытый (opaque) объект, который специфицирует две вещи: последовательность базовых типов и последовательность смещений. Последовательность таких пар определяется как отображение (карта) типа:

Typemap = {(type0, disp0), ... , (typen-1, dispn-1)}

Значения смещений не обязательно должны быть неотрицательными, различными и упорядоченными по возрастанию. Отображение типа вместе с базовым адресом начала расположения данных buf определяет коммуникационный буфер обмена. Этот буфер будет содержать n элементов, а i-й элемент будет иметь адрес buf+disp и иметь базовый тип type. Стандартные типы MPI имеют предопределенные отображения типов. Например, MPI_INT имеет отображение {(int,0)}.

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

Стандартный сценарий определения и использования производных типов включает следующие шаги:

Любой тип данных в MPI имеет две характеристики: протяженность и размер, выраженные в байтах:

Для простых типов протяженность и размер совпадают.

Функция MPI_Type_extent определяет протяженность элемента некоторого типа.

C:
int MPI_Type_extent(MPI_Datatype datatype, MPI_Aint *extent)
FORTRAN:
MPI_TYPE_EXTENT(DATATYPE, EXTENT, IERROR)
INTEGER DATATYPE, EXTENT, IERROR
IN datatype - тип данных;
OUT extent - протяженность элемента заданного типа.

Функция MPI_Type_size определяет "чистый" размер элемента некоторого типа (за вычетом пустых промежутков).

C:
int MPI_Type_size(MPI_Datatype datatype, int *size)
FORTRAN:
MPI_TYPE_SIZE(DATATYPE, SIZE, IERROR)
INTEGER DATATYPE, SIZE, IERROR
IN datatype - тип данных;
OUT size - размер элемента заданного типа.

Как отмечалось выше, для создания производных типов в MPI имеется набор специальных функций-конструкторов. Рассмотрим их в последовательности от простого к сложному.

Самый простой конструктор типа MPI_Type_contiguous создает новый тип, элементы которого состоят из указанного числа элементов базового типа, занимающих смежные области памяти.

C:
int MPI_Type_contiguous(int count, MPI_Datatype oldtype,
MPI_Datatype *newtype)
FORTRAN:
MPI_TYPE_CONTIGUOUS(COUNT, OLDTYPE, NEWTYPE, IERROR)
INTEGER COUNT, OLDTYPE, NEWTYPE, IERROR
IN count - число элементов базового типа;
IN oldtype - базовый тип данных;
OUT newtype - новый производный тип данных.

Графическая интерпретация работы конструктора MPI_Type_contiguousа приведена на рис. 5.1.

Рис. 5.1. Графическая интерпретация работы конструктораа MPI_Type_contiguous.

Конструктор типа MPI_Type_vector создает тип, элемент которого представляет собой несколько равноудаленных друг от друга блоков из одинакового числа смежных элементов базового типа.

C:
int MPI_Type_vector(int count, int blocklength, int stride,
MPI_Datatype oldtype, MPI_Datatype *newtype)
FORTRAN:
MPI_TYPE_VECTOR(COUNT, BLOCKLENGTH, STRIDE, OLDTYPE,
NEWTYPE, IERROR)
INTEGER COUNT, BLOCKLENGTH, STRIDE, OLDTYPE, NEWTYPE, IERROR
IN count - число блоков;
IN blocklength - число элементов базового типа в каждом блоке;
IN stride - шаг между началами соседних блоков, измеренный числом элементов базового типа;
IN oldtype - базовый тип данных;
OUT newtype - новый производный тип данных.

Функция создает тип newtype, элемент которого состоит из count блоков, каждый из которых содержит одинаковое число blocklength элементов типа oldtype. Шаг stride между началом блока и началом следующего блока всюду одинаков и кратен протяженности представления базового типа. Графическая интерпретация работы конструктора MPI_Type_vector приведена на рис. 5.2.

Рис. 5.2. Графическая интерпретация работы конструктора MPI_Type_vector.

Конструктор типа MPI_Type_hvector расширяет возможности конструктора MPI_Type_vector, позволяя задавать произвольный шаг между началами блоков в байтах.

C:
int MPI_Type_hvector(int count, int blocklength, MPI_Aint stride,
MPI_Datatype oldtype, MPI_Datatype *newtype)
FORTRAN:
MPI_TYPE_HVECTOR(COUNT, BLOCKLENGTH, STRIDE, OLDTYPE,
NEWTYPE, IERROR)
INTEGER COUNT, BLOCKLENGTH, STRIDE, OLDTYPE, NEWTYPE, IERROR
IN count - число блоков;
IN blocklength - число элементов базового типа в каждом блоке;
IN stride - шаг между началами соседних блоков в байтах;
IN oldtype - базовый тип данных;
OUT newtype - новый производный тип данных.

Графическая интерпретация работы конструктора MPI_Type_hvector приведена на рис. 5.3.

Рис. 5.3. Графическая интерпретация работы конструктора MPI_Type_hvector.

Конструктор типа MPI_Type_indexed является более универсальным конструктором по сравнению с MPI_Type_vector, так как элементы создаваемого типа состоят из произвольных по длине блоков с произвольным смещением блоков от начала размещения элемента. Смещения измеряются в элементах старого типа.

C:
int MPI_Type_indexed(int count, int *array_of_blocklengths,
int *array_of_displacements, MPI_Datatype oldtype,
MPI_Datatype *newtype)
FORTRAN:
MPI_TYPE_INDEXED(COUNT, ARRAY_OF_BLOCKLENGTHS,
ARRAY_OF_DISPLACEMENTS, OLDTYPE, NEWTYPE, IERROR)
INTEGER COUNT, ARRAY_OF_BLOCKLENGTHS(*), ARRAY_OF_DISPLACEMENTS(*),
OLDTYPE, NEWTYPE, IERROR
IN count - число блоков;
IN array_of_blocklengths - массив, содержащий число элементов базового типа в каждом блоке;
IN array_of_displacements - массив смещений каждого блока от начала размещения элемента нового типа, смещения измеряются числом элементов базового типа;
IN oldtype - базовый тип данных;
OUT newtype - новый производный тип данных.

Эта функция создает тип newtype, каждый элемент которого состоит из count блоков, где i-ый блок содержит array_of_blocklengths[i] элементов базового типа и смещен от начала размещения элемента нового типа на array_of_displacements[i] элементов базового типа. Графическая интерпретация работы конструктора MPI_Type_indexedа приведена на рис. 5.4.

Рис. 5.4. Графическая интерпретация работы конструктора MPI_Type_indexed.

Конструктор типа MPI_Type_hindexed идентичен конструктору MPI_Type_indexed за исключением того, что смещения измеряются в байтах.

C:
int MPI_Type_hindexed(int count, int *array_of_blocklengths,
MPI_Aint *array_of_displacements, MPI_Datatype oldtype,
MPI_Datatype *newtype)
FORTRAN:
MPI_TYPE_HINDEXED(COUNT, ARRAY_OF_BLOCKLENGTHS,
ARRAY_OF_DISPLACEMENTS, OLDTYPE, NEWTYPE, IERROR)
INTEGER COUNT, ARRAY_OF_BLOCKLENGTHS(*), ARRAY_OF_DISPLACEMENTS(*),
OLDTYPE, NEWTYPE, IERROR
IN count - число блоков;
IN array_of_blocklengths - массив, содержащий число элементов базового типа в каждом блоке;
IN array_of_displacements - массив смещений каждого блока от начала размещения элемента нового типа, смещения измеряются в байтах;
IN oldtype - базовый тип данных;
OUT newtype - новый производный тип данных.

Элемент нового типа состоит из count блоков, где i-ый блок содержит array_of_blocklengths[i] элементов старого типа и смещен от начала размещения элемента нового типа на array_of_displacements[i] байт. Графическая интерпретация работы конструктора MPI_Type_hindexed приведена на рис. 5.5.

Рис. 5.5. Графическая интерпретация работы конструктора MPI_Type_hindexed.

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

C:
int MPI_Type_struct(int count, int *array_of_blocklengths,
MPI_Aint *array_of_displacements, MPI_Datatype *array_of_types,
MPI_Datatype *newtype)
FORTRAN:
MPI_TYPE_STRUCT(COUNT, ARRAY_OF_BLOCKLENGTHS,
ARRAY_OF_DISPLACEMENTS, ARRAY_OF_TYPES, NEWTYPE, IERROR)
INTEGER COUNT, ARRAY_OF_BLOCKLENGTHS(*), ARRAY_OF_DISPLACEMENTS(*),
ARRAY_OF_TYPES(*), NEWTYPE, IERROR
IN count - число блоков;
IN array_of_blocklength - массив, содержащий число элементов одного из базовых типов в каждом блоке;
IN array_of_displacements - массив смещений каждого блока от начала размещения структуры, смещения измеряются в байтах;
IN array_of_type - массив, содержащий тип элементов в каждом блоке;
OUT newtype - новый производный тип данных.

Функция создает тип newtype, элемент которого состоит из count блоков, где i-ый блок содержит array_of_blocklengths[i] элементов типа array_of_types[i]. Смещение i-ого блока от начала размещения элемента нового типа измеряется в байтах и задается в array_of_displacements[i].

Графическая интерпретация работы конструктора MPI_Type_struct приведена на рис. 5.6.

Рис. 5.6. Графическая интерпретация работы конструктора MPI_Type_struct.

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

C:
int MPI_Type_commit(MPI_Datatype *datatype)
FORTRAN:
MPI_TYPE_COMMIT(DATATYPE, IERROR)
INTEGER DATATYPE, IERROR

INOUT datatype   - новый производный тип данных.

Функция MPI_Type_free уничтожает описатель производного типа.

C:
int MPI_Type_free(MPI_Datatype *datatype)
FORTRAN:
>
MPI_TYPE_FREE(DATATYPE, IERROR)
INTEGER DATATYPE, IERROR

INOUT datatype   - уничтожаемый производный тип.

Функция MPI_Type_free устанавливает описатель типа в состояние MPI_DATATYPE_NULL. Это не повлияет на выполняющиеся в данный момент коммуникационные операции с этим типом данных и на производные типы, которые ранее были определены через уничтоженный тип.

Для определения длины сообщения используются две функции: MPI_Get_count и MPI_Get_elements. Для сообщений из простых типов они возвращают одинаковое число. Подпрограмма MPI_Get_count возвращает число элементов типа datatype, указанного в операции получения. Если получено не целое число элементов, то она возвратит константу MPI_UNDEFINED (функция MPI_Get_count рассматривалась в разделе 3.2., посвященном коммуникационным операциям типа точка-точка).

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

C:
int MPI_Get_elements(MPI_Status *status, MPI_Datatype datatype,
int *count)
FORTRAN:
MPI_GET_ELEMENTS(STATUS, DATATYPE, COUNT, IERROR)
INTEGER STATUS(MPI_STATUS_SIZE), DATATYPE, COUNT, IERROR
IN status - статус сообщения;
IN datatype - тип элементов сообщения;
OUT count - число элементов простых типов, содержащихся в сообщении.



Next:5.2. Передача упакованных данных
Up:5. ПРОИЗВОДНЫЕ ТИПЫ ДАННЫХ И ПЕРЕДАЧА УПАКОВАННЫХ ДАННЫХ
Prev:5. ПРОИЗВОДНЫЕ ТИПЫ ДАННЫХ И ПЕРЕДАЧА УПАКОВАННЫХ ДАННЫХ