next up previous contents
Next: Адресные функции и функции Up: Производные типы данных Previous: Производные типы данных   Contents

Конструкторы типа данных

Contiguous. Простейшим типом конструктора типа данных является конструктор MPI_TYPE_CONTIGUOUS, который позволяет копировать тип данных в смежные области.

Синтаксис функции MPI_TYPE_CONTIGUOUS представлен ниже.

MPI_TYPE_CONTIGUOUS (count, oldtype, newtype)

IN count число повторений (неотрицательное целое)
IN oldtype старый тип данных (дескриптор)
OUT newtype новый тип данных (дескриптор)

int MPI_Type_contiguous(int count, MPI_Datatype oldtype, MPI_Datatype *newtype) MPI_TYPE_CONTIGUOUS(COUNT, OLDTYPE, NEWTYPE, IERROR) INTEGER COUNT, OLDTYPE, NEWTYPE, IERROR MPI::Datatype MPI::Datatype::Create_contiguous (int count) const

Новый тип newtype есть тип, полученный конкатенацией (сцеплением) count копий старого типа oldtype.

Пример 3.20 Пусть oldtype имеет карту type map { ( double, 0), (char, 8) } с длиной 16 и пусть count = 3. Карта нового типа будет:

{ (double, 0), (char, 8), (double, 16), (char, 24), (double, 32), (char, 40) } ;

то есть содержать меняющиеся удвоенные значения и символьные элементы со смещением 0, 8, 16, 24, 32, 40.

В общем предположим, что карта типа для oldtype есть

{ (type$_{0}$,disp$_{0}$), ..., (type$_{n - 1}$, disp$_{n - 1}$)} ,

с длиной ex, Тогда newtype имеет карту с count $\cdot
$ n элементами, определяемыми:

{ (type$_{0}$, disp$_{0}$), ..., (type$_{n - 1}$, disp$_{n - 1}$), (type$_{0}$, disp$_{0}$+ex), ... ,(type$_{n - 1}$, disp$_{n - 1}$+ ex) , ...

(type$_{0}$, disp$_{0}$+ex $\cdot
$ ( count-1)), ... , (type$_{n - 1}$, disp$_{n - 1}$+ ex $\cdot
$ (count-1)) }.

Vector. Функция MPI_TYPE_VECTOR является более универсальным конструктором, который позволяет реплицировать типы данных в области, состоящие из блоков равного объема. Каждый блок получается конкатенацией некоторого количества копий старого типа. Пространство между блоками кратно размеру old datatype.

Синтаксис функции MPI_TYPE_VECTOR представлен ниже.

MPI_TYPE_VECTOR(count, blocklength, stride, oldtype, newtype)

IN count число блоков (неотрицательное целое)
IN blocklength число элементов в каждом блоке (неотрицательное целое)
IN stride число элементов между началами каждого блока (целое)
IN oldtype старый тип данных (дескриптор)
OUT newtype новый тип данных (дескриптор)

int MPI_Type_vector(int count, int blocklength, int stride, MPI_Datatype oldtype, MPI_Datatype *newtype) MPI_TYPE_VECTOR(COUNT, BLOCKLENGTH, STRIDE, OLDTYPE, NEWTYPE, IERROR) INTEGER COUNT, BLOCKLENGTH, STRIDE, OLDTYPE, NEWTYPE, IERROR MPI::Datatype MPI::Datatype::Create_vector(int count, int blocklength, int stride) const

Пример 3.21 Предположим снова, что oldtype имеет карту type map {(double, 0), (char, 8)}, с размером 16. Обращение MPI_TYPE_VECTOR(2, 3, 4, oldtype, newtype) будет создавать тип с картой:

type map, { (double, 0), (char, 8), (double, 16), (char, 24), ( double, 32), (char, 40),

(double, 64), (char, 72), (double, 80), (char, 88), (double, 96), (char, 104) } .

Это означает, что в новой карте есть два блока, каждый с тремя копиями старого типа, со страйдом (stride) 4 элемента (4$\cdot
$16 байтов) между блоками.

Пример 3.22 Обращение MPI_TYPE_VECTOR(3, 1, -2, oldtype, newtype) будет создавать тип:

{ (double, 0), (char, 8), (double, -32), (char, -24), (double, -64), (char, -56) } .

В общем случае предположим, что oldtype имеет карту:

{ (type$_{0}$, disp$_{0}$), ..., (type$_{n - 1}$, disp$_{n - 1}$) },

с экстентом ex. Пусть bl - длина блока. Вновь созданный тип данных будет иметь карту с
$ count \times bl \times n $ элементами:

{ (type$_{0}$, disp$_{0}$), ... , (type$_{n - 1}$, disp$_{n - 1}$),

(type$_{0}$,disp$_{0}$+ ex) , ... , (type$_{n - 1}$, disp$_{n - 1}$+ ex), ...,

(type$_{0}$, disp$_{0}$+ (bl -1) $\cdot
$ ex) , ... , (type$_{n - 1}$, disp$_{n - 1}$+ (bl -1) $\cdot
$ ex) ,

(type$_{0}$,disp$_{0}$+ stride$\cdot
$ ex) , ... , (type$_{n - 1}$, disp$_{n - 1}$+ stride$\cdot
$ ex), ... ,

(type$_{0}$, disp$_{0}$+ (stride + bl -1) $\cdot
$ ex) , ... , (type_n-1, disp_n-1+ (stride + bl -1) $\cdot
$ex) , ....,

(type$_{0}$,disp$_{0}$+ stride $\cdot
$ (count-1) $\cdot
$ ex), ... ,

(type$_{n - 1}$, disp$_{n - 1}$+ stride $\cdot
$ (count -1) $\cdot
$ ex) , ... ,

(type$_{0}$, disp$_{0}$+ (stride $\cdot
$ (count -1) + bl -1)$\cdot
$ ex) , ... ,

(type$_{n - 1}$, disp$_{n - 1}$+ ( stride $\cdot
$ (count -1) + bl -1) $\cdot
$ ex) } .

Обращение к MPI_TYPE_CONTIGUOUS (count, oldtype, newtype) эквивалентно обращению
MPI_TYPE_VECTOR(count, 1, 1, oldtype, newtype) или обращению MPI_TYPE_VECTOR (1, count, n, oldtype, newtype), где n - произвольное.

Hvector. Функция MPI_TYPE_HVECTOR идентична MPI_TYPE_VECTOR за исключением того, что страйд задается в байтах, а не в элементах. Использование обоих типов векторных конструкторов иллюстрируется в разделе 3.12.7. (H обозначает heterogeneous - неоднородный).

Синтаксис функции MPI_TYPE_HVECTOR представлен ниже.

MPI_TYPE_HVECTOR(count, blocklength, stride, oldtype, newtype)

IN count число блоков (неотрицательное целое)
IN blocklength число элементов в каждом блоке (неотрицательное целое)
IN stride число байтов между стартом каждого блока (целое)
IN oldtype старый тип данных (дескриптор)
OUT newtype новый тип данных (дескриптор)

int MPI_Type_hvector(int count, int blocklength, MPI_Aint stride, MPI_Datatype oldtype, MPI_Datatype *newtype) MPI_TYPE_HVECTOR(COUNT, BLOCKLENGTH, STRIDE, OLDTYPE, NEWTYPE, IERROR) INTEGER COUNT, BLOCKLENGTH, STRIDE, OLDTYPE, NEWTYPE, IERROR MPI::Datatype MPI::Datatype::Create_hvector(int count, int blocklength, MPI::Aint stride) const

Предположим, что oldtype имеет карту

{ (type$_{0}$, disp$_{0}$), ..., (type$_{n - 1}$, disp$_{n - 1}$) } ,

с расширением ex. Пусть bl - длина блока. Вновь созданный тип данных будет иметь карту с $ count \times bl \times n $ элементами:

{ (type$_{0}$, disp$_{0}$), ... , (type$_{n - 1}$, disp$_{n - 1}$),

(type$_{0}$,disp$_{0}$+ ex) , ... , (type$_{n - 1}$, disp$_{n - 1}$+ ex), ...,

(type$_{0}$, disp$_{0}$+ (bl -1) $\cdot
$ ex) , ... , (type$_{n - 1}$, disp$_{n - 1}$+ (bl -1)$\cdot
$ ex) ,

(type$_{0}$,disp$_{0}$+ stride) , ... , (type$_{n - 1}$, disp$_{n - 1}$+ stride) , ... ,

(type$_{0}$, disp$_{0}$+ stride + ( bl -1)$\cdot
$ ex) , ... ,

(type$_{n - 1}$, disp$_{n - 1}$+ stride + (bl -1)$\cdot
$ ex) , ....,

(type$_{0}$,disp$_{0}$+ stride $\cdot
$ (count-1)) , ... , (type$_{n - 1}$, disp$_{n - 1}$+ stride $\cdot
$(count -1)) , ... ,

(type$_{0}$, disp$_{0}$+ stride $\cdot
$ (count -1) + (bl -1)$\cdot
$ ex) , ... ,

(type$_{n - 1}$, disp$_{n - 1}$+ stride $\cdot
$ (count -1) + (bl -1) $\cdot
$ ex) } .

Indexed. Функция MPI_TYPE_INDEXED позволяет реплицировать старый тип old datatype в последовательность блоков (каждый блок есть конкатенация old datatype), где каждый блок может содержать различное число копий и иметь различное смещение. Все смещения блоков кратны длине старого блока old type.

Синтаксис функции MPI_TYPE_INDEXED представлен ниже.

MPI_TYPE_INDEXED(count, array_of_blocklengths, array_of_displacements, oldtype, newtype)

IN count число блоков
IN array_of_blocklengths число элементов в каждом блоке (массив неотрицательных целых)
IN array_of_displacements смещение для каждого блока (массив целых)
IN oldtype старый тип данных (дескриптор)
OUT newtype новый тип данных (дескриптор)

int MPI_Type_indexed(int count, int *array_of_blocklengths, int *array_of_displacements, MPI_Datatype oldtype, MPI_Datatype *newtype) MPI_TYPE_INDEXED(COUNT, ARRAY_OF_BLOCKLENGTHS, ARRAY_OF_DISPLACEMENTS, OLDTYPE, NEWTYPE, IERROR) INTEGER COUNT, ARRAY_OF_BLOCKLENGTHS(*), ARRAY_OF_DISPLACEMENTS(*), OLDTYPE, NEWTYPE, IERROR MPI::Datatype MPI::Datatype::Create_indexed(int count, const int array_of_blocklengths[], const int array_of_displacements[]) const

Пример 3.23 Пусть oldtype имеет карту type map { ( double, 0), (char, 8) } с экстентом16. Пусть B = (3, 1) и D = (4, 0). Обращение MPI_TYPE_INDEXED (2, B, D, oldtype, newtype) возвращает тип данных с картой:

{ (double, 64), (char, 72), (double, 80), (char, 88), (double, 96), (char, 104),

(double, 0), (char, 8) } .

Это означает, что в новом типе имеется три копии старого типа old type, начиная со смещения 64 и одна копия стартует со смещения 0.

В общем случае предположим, что oldtype имеет карту

{ (type$_{0}$, disp$_{0}$), ..., (type$_{n - 1}$, disp$_{n - 1}$) } ,

с экстентом ex. Пусть В является аргументом массива длин и D - аргументом массива смещений. Тогда вновь созданный тип данных имеет $n \times (B[0]+B[1]+\ldots +B[count-1])$ элементов:

{(type$_{0}$, disp$_{0}$+ D[0] $
* $ex),..., (type$_{n - 1}$, disp$_{n - 1}$ + D[0]$
* $ex)

(type$_{0}$, disp$_{0}$+ D[0] +B[0] -1)$
* $ex),..., (type$_{n - 1}$, disp$_{n - 1}$ + (D[0] + В[0] -1)$
* $ex),...,

(type$_{0}$, disp$_{0}$+ D[count - 1]$
* $ex),..., (type$_{n - 1}$, disp$_{n - 1}$ + D[count - 1]$
* $ex)... ,

(type$_{0}$, disp$_{0}$+ (D[count - 1] + B[count -1)$
* $ex),...,

(type$_{n - 1}$, disp$_{n - 1}$+$_{ (}$D[count - 1] + B[count -1)$
* $ex).

Обращение к MPI_TYPE_VECTOR (count, blocklength, stride, oldtype, newtype) будет эквивалентно обращению к MPI_TYPE_INDEXED(count, B, D, oldtype, newtype), где

D[j] = j$
* $ strade, j = 0,..., count - 1,

и

B[j] = blocklength, j = 0,..., count - 1

Hindexed. Функция MPI_TYPE_HINDEXED идентична MPI_TYPE_INDEXED, за исключением того, что смещения блоков в массиве array_of_displacements задаются в байтах, а не в кратностях величины старого типа oldtype.

Синтаксис функции MPI_TYPE_HINDEXED представлен ниже.

MPI_TYPE_HVECTOR(count, blocklength, stride, oldtype, newtype)

IN count число блоков (неотрицательное целое)
IN blocklength число элементов в каждом блоке (неотрицательное целое)
IN stride число байтов между стартом каждого блока (целое)
IN oldtype старый тип данных (дескриптор)
OUT newtype новый тип данных (дескриптор)

int MPI_Type_hvector(int count, int blocklength, MPI_Aint stride, MPI_Datatype oldtype, MPI_Datatype *newtype) MPI_TYPE_HVECTOR(COUNT, BLOCKLENGTH, STRIDE, OLDTYPE, NEWTYPE, IERROR) INTEGER COUNT, BLOCKLENGTH, STRIDE, OLDTYPE, NEWTYPE, IERROR MPI::Datatype MPI::Datatype::Create_hvector(int count, int blocklength, MPI::Aint stride) const

Предположим, что oldtype имеет карту

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

с расширением ex. Пусть В - это аргумент array_of_blocklength, а D - аргумент
array_of_displacements. Вновь созданный тип данных имеет карту с $n \times (B[0]+B[1]+\ldots +B[count-1])$ элементов:

{(type$_{0}$,disp$_{0}$+ D[0]),..., (type$_{n - 1}$, disp$_{n - 1}$+ D[0]),...,

(type$_{0}$, disp$_{0}$+ D[0] + (B[0] -1)$
* $ex),...,

(type$_{n - 1, }$disp$_{n - 1}$+ D[0] + (B[0] -1)$
* $ex),...,

(type$_{0}$, disp$_{0}$+ D[count - 1]),..., (type$_{n - 1, }$disp$_{n - 1}$+ D[count - 1]), ...,

(type$_{0}$, disp$_{0}$+ D[count - 1]) + (B[count - 1] - 1)$
* $ex),...,

(type$_{n - 1, }$disp$_{n - 1}$+ D[count - 1]) + (B[count - 1] - 1)$
* $ex)}

Struct. MPI_TYPE_STRUCT является наиболее общим типом конструктора. Он отличается от предыдущего тем, что позволяет каждому блоку состоять из репликаций различного типа.

Синтаксис функции MPI_TYPE_STRUCT представлен ниже.

=1cm MPI_TYPE_STRUCT(count, array_of_blocklengths,
array_of_displacements, array_of_types, newtype)

IN count число блоков (целое)
IN array_of_blocklength число элементов в каждом блоке (массив целых)
IN array_of_displacements смещение каждого блока в байтах (массив целых)
IN array_of_types тип элементов в каждом блоке (массив дескрипторов объектов типов данных)
OUT newtype новый тип данных (дескриптор)

=1cm int MPI_Type_struct(int count, int *array_of_blocklengths,
MPI_Aint *array_of_displacements, MPI_Datatype *array_of_types,
MPI_Datatype *newtype)

=1cm 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

Пример 3.24 Пусть 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_HINDEXED(count, B, D, oldtype, newtype) эквивалентно обращению к MPI_TYPE_STRUCT(count, B, D, T, newtype), где каждый вход T равен oldtype.


next up previous contents
Next: Адресные функции и функции Up: Производные типы данных Previous: Производные типы данных   Contents
Alex Otwagin 2002-12-10