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 определяет протяженность элемента некоторого типа.
IN | datatype | - тип данных; |
OUT | extent | - протяженность элемента заданного типа. |
Функция MPI_Type_size определяет "чистый" размер элемента некоторого типа (за вычетом пустых промежутков).
IN | datatype | - тип данных; |
OUT | size | - размер элемента заданного типа. |
Как отмечалось выше, для создания производных типов в MPI имеется набор специальных функций-конструкторов. Рассмотрим их в последовательности от простого к сложному.
Самый простой конструктор типа MPI_Type_contiguous создает новый тип, элементы которого состоят из указанного числа элементов базового типа, занимающих смежные области памяти.
IN | count | - число элементов базового типа; |
IN | oldtype | - базовый тип данных; |
OUT | newtype | - новый производный тип данных. |
Графическая интерпретация работы конструктора MPI_Type_contiguousа приведена на рис. 5.1.
Рис. 5.1. Графическая интерпретация работы конструктораа MPI_Type_contiguous.
Конструктор типа MPI_Type_vector создает тип, элемент которого представляет собой несколько равноудаленных друг от друга блоков из одинакового числа смежных элементов базового типа.
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, позволяя задавать произвольный шаг между началами блоков в байтах.
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, так как элементы создаваемого типа состоят из произвольных по длине блоков с произвольным смещением блоков от начала размещения элемента. Смещения измеряются в элементах старого типа.
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 за исключением того, что смещения измеряются в байтах.
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 - самый универсальный из всех конструкторов типа. Создаваемый им тип является структурой, состоящей из произвольного числа блоков, каждый из которых может содержать произвольное число элементов одного из базовых типов и может быть смещен на произвольное число байтов от начала размещения структуры.
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 регистрирует созданный производный тип. Только после регистрации новый тип может использоваться в коммуникационных операциях.
INOUT datatype - новый производный тип данных.
Функция MPI_Type_free уничтожает описатель производного типа.
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 возвращает число элементов простых типов, содержащихся в сообщении.
IN | status | - | статус сообщения; |
IN | datatype | - | тип элементов сообщения; |
OUT | count | - | число элементов простых типов, содержащихся в сообщении. |