next up previous contents
Next: MPI и треды Up: Внешние интерфейсы Previous: Классы ошибок, коды ошибок   Contents

Расшифровка типов данных

В MPI-1 реализованы объекты, являющиеся типами данных, которые позволяют пользователям указывать способ размещения данных в памяти. Информация о размещении, однажды помещенная в тип данных, не может быть выделена из типа данных с помощью функций MPI-1. В ряде случаев, однако, хотелось бы иметь доступ к информации о размещении для скрытых объектов -типов данных.

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

MPI_TYPE_GET_ENVELOPE(datatype, num_integers, num_addresses, num_datatypes, combiner)

IN datatype Тип данных для доступа (указатель)  
OUT num_integers Количество входных чисел , использованных при вызове конструирующего комбинера (неотрицательное целое)  
OUT num_addresses Количество входных адресов , использованных при вызове конструирующего комбинера (неотрицательное целое)  
OUT num_datatypes Количество входных типов данных , использованных при вызове конструирующего комбинера (неотрицательное целое)  
OUT combiner Комбинер (состояние)  

int MPI_Type_get_envelope(MPI_Datatype datatype, int *num_integers, int *num_addresses, int *num_datatypes, int *combiner)

MPI_TYPE_GET_ENVELOPE(DATATYPE, NUM_INTEGERS, HUM_ADDRESSES, NUM_DATATYPES, COMBINER, IERROR) INTEGER DATATYPE, NUM_INTEGERS, NUM_ADDRESSES, NUM_DATATYPES, COMBINER, IERROR

void MPI::Datatype::Get_envelope(int& num_integers, int& num_addresses, int& num_datatypes, int& combiner) const

Для заданного типа данных MPI_TYPE_GET_ENVELOPE возвращает информацию о количестве и типе входных аргументов, использованных в вызове, который создал datatype. Возвращенные значения ``количества аргументов'' могут быть использованы для реализации достаточно больших массивов в расшифровывающей подпрограмме MPI_TYPE_GET_CONTENTS. Этот вызов и значение возвращаемых данных описаны ниже. combiner отображает конструктор типа данных MPI, который использовался для создания datatype.

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

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

Совет пользователям: Расшифровка и затем повторная шифровка типов данных не обязательно дадут точную копию. Кэшированная информация не восстанавливается подобным механизмом. Это должно быть скопирована другими методами (принимая во внимание все известные ключи). Функция дублирования типа данных из раздела 1-3.4.1 может использоваться для получения точной копии первоначального типа данных.

Таблица 6.1 содержит значения, которые могут быть возвращены в combiner, слева и связанные с ними вызовы справа.

Если combiner - это MPI_COMBINER_NAMED, то datatype - это имя предопределенного типа данных.

Для вызовов с адресами в качестве аргументов, иногда нужно отличать: вызов использовал целочисленный или адресный аргумент. Например, есть два комбинера для hvector:
MPI_COMBINER_HVECTOR_INTEGER и MPI_COMBINER_HVECTOR. Первый используется, если был вызов MPI-1 из ФОРТРАНa, а второй - если был вызов MPI-1 из Си или С++. Однако, в системах, где MPI_ADDRESS_KIND = MPI_INTEGER_KIND (то есть, где целочисленные и адресные параметры совпадают) комбинер MPI_COMBINER_HVECTOR может быть возвращен для типа данных, построенного вызовом MPI_TYPE_HVECTOR из ФОРТРАНa. Точно так же, MPI_COMBINER_HINDEXED может быть возвращен для типа, построенного вызовом MPI_TYPE_HINDEXED из ФОРТРАНa, а MPI_COMBINER_STRUCT может быть возвращен для типа данных, сконструированного вызовом MPI_TYPE_STRUCT из ФОРТРАНa. Для подобных систем не требуется отличать конструкторы, которые принимают адресные аргументы, от конструкторов, принимающих целочисленные аргументы, так как они совпадают. Все новые MPI-2 вызовы используют адресные аргументы.

MPI_COMBINER_NAMED именованный предопределенный тип  
MPI_COMBINER_DUP MPI_TYPE_DUP  
MPI_COMBINER_CONTIGUOUS MPI_TYPE_CONTIGUOUS  
MPI_COMBINER_VECTOR MPI_TYPE_VECTOR  
MPI_COMBINER_HVECTOR_INTEGER MPI_TYPE_HVECTOR из ФОРТРАНa  
MPI_COMBINER_HVECTOR MPI_TYPE_HVECTOR из Си или С++ и в некоторых случаях ФОРТРАНa, или же MPI_TYPE_CREATE_HVECTOR  
MPI_COMBINER_INDEXED MPI_TYPE_INDEXED  
MPI_COMBINER_HINDEXED_INTEGER MPI_TYPE_HINDEXED из ФОРТРАНa  
MPI_COMBINER_HINDEXED MPI_TYPE_HINDEXED из Си или С++ и в некоторых случаях ФОРТРАНa, или же MPI_TYPE_CREATE_HINDEXED  
MPI_COMBINER_INDEXED_BLOCK MPI_TYPE_CREATE_INDEXED_BLOCK  
MPI_COMBINER_STRUCT_INTEGER MPI_TYPE_STRUCT из ФОРТРАНa  
MPI_COMBINER_STRUCT MPI_TYPE_STRUCT из Си или С++ и в некоторых случаях ФОРТРАНa, или же MPI_TYPE_CREATE_STRUCT  
MPI_COMBINER_SUBARRAY MPI_TYPE_CREATE_SUBARRAY  
MPI_COMBINER_DARRAY MPI_TYPE_CREATE_DARRAY  
MPI_COMBINER_F90_REAL MPI_TYPE_CREATE_F90_REAL  
MPI_COMBINER_F90_COMPLEX MPI_TYPE_CREATE_F90_COMPLEX  
MPI_COMBINER_F90_INTEGER MPI_TYPE_CREATE_F90_INTEGER  
MPI_COMBINER_RESIZED MPI_TYPE_CREATE_RESIZED  

Объяснение: Чтобы воссоздать первоначальный вызов, важно знать, была ли адресная информация усечена. Вызовы MPI-1 из ФОРТРАНa для нескольких подпрограмм могут являться усекающими субъектами в случае, когда заданная по умолчанию длина INTEGER меньше, чем размер адреса.

Фактические аргументы, использованные при вызове для создания datatype, можут быть получены с помощью вызова:

MPI_TYPE_GET_CONTENTS(datatype, max_integers, max_addresses, max_datatypes, array_of_integers, array_of_addresses, array_of_datatypes)

IN datatype Тип данных для доступа (указатель)  
IN num_integers Количество элементов в массиве array_of_integers (неотрицательное целое)  
IN num_addresses Количество элементов в массиве array_of_addresses (неотрицательное целое)  
IN num_datatypes Количество элементов в массиве array_of_datatypes (неотрицательное целое)  
OUT array_of_integers Содержит целочисленные аргументы, использованные при конструировании datatype (массив целых чисел)  
OUT array_of_addresses Содержит адресные аргументы, использованные при конструировании datatype (массив целых чисел)  
OUT array_of_datatypes Содержит аргументы-типы данных, использованные при конструировании datatype (массив указателей)  

int MPI_Type_get_contents(MPI_Datatype datatype, int max_integers, int max_addresses, int max_datatypes, int *array_of_integers, MPI_Aint *array_of_addresses, MPIJDatatype *array_of_datatypes)

MPI_TYPE_GET_CONTENTS(DATATYPE, MAX_INTEGERS, MAX_ADDRESSES, MAX_DATATYPES, ARRAY_OF_INTEGERS, ARRAY_OF_ADDRESSES, ARRAY_OF_DATATYPES, IERROR) INTEGER DATATYPE, MAX_INTEGERS, MAX_ADDRESSES, MAX_DATATYPES, ARRAY_OF_INTEGERS (*), ARRAY_OF_DATATYPES (*), IERROR INTEGER(KIND=MPI_ADDRESS_KIND) ARRAY_OF_ADDRESSES (*)

void MPI::Datatype::Get_contents(int max_integers, int max_addresses, int max_datatypes, int array_of_integers[], MPI::Aint array_of_addresses[], MPI::Datatype array_of_datatypes[]) const

datatype должен быть предопределенным неименованным или производным типом данных; вызов ошибочен, если datatype является предопределенным именованным типом данных.

Значения, присвоенные max_integers, max_addresses, и max_datatypes должны быть по крайней мере такого же размера, как и значение, возвращенное в num_integers, num_addresses, и num_datatypes, соответственно, при вызове MPI_TYPE_GET_ENVELOPE с тем же самым аргументом datatype.

Объяснение: Аргументы max_integers, max_addresses, и max_datatypes подвержены проверке на ошибки в вызове. Это происходит аналогично для аргументов в топологии подпрограмм MPI-1.

Типы данных, возвращенные в array_of_datatypes - это указатели на объеткы-типы данных, которые эквивалентны типам данных, использованным в первоначальном конструирующем запросе. Если они были производными типами данных, то возвращенные типы данных являются новыми объектами-типами данных, и пользователь ответственен за их освобождение с помощью MPI_TYPE_FREE. Если они были предопределенными типами данных, то возвращенный тип данных эквивалентен предопределенному и не может быть освобожден.

Переданное состояние возвращенных производных типов данных неопределено; то есть типы данных могут или не могут быть переданными. Кроме того, и содержимое атрибутов возвращаемых типов данных неопределено.

Обратите внимание на то, что MPI_TYPE_GET_CONTENTS может быть вызван с аргументом datatype, который был сконструирован с использованием MPI_TYPE_CREATE_F90_REAL,
MPI_TYPE_CREATE_F90_INTEGER или MPI_TYPE_CREATE_F90_COMPLEX (неименованный предопреде-
ленный тип данных). В таком случае, возвращается пустой array_of_datatypes.

Объяснение: Определение эквивалентности типов данных подразумевает, что предопределенные типы данных равны. При потребности в одинаковых указателях для именованных предопределенных типов данных возможно использование операторов сравнения = = или .EQ. для определения вызываемого типа данных. []

Совет разработчикам: Типы данных, возвращенные в array_of_datatypes, должны представляться пользователю так, как будто каждый из них - эквивалентная копия типа данных, использованного в конструирующем тип вызове. Сделано ли это при создании нового типа данных, или с помощью другого механизма, подобного механизму подсчета ссылок, это не требует выполнения, пока семантика сохраняется.[]

Объяснение: Переданное состояние и атрибуты возвращенного типа данных преднамеренно
оставлены неопределенными. Тип данных, используемый в первоначальной конструкции, возможно, был изменен с тех пор, когда он использовался при вызове конструктора. Атрибуты могут быть добавлены, удалены или модифицированы так же успешно, как факт передачи типа данных. Семантика позволяет реализации подсчитывать ссылки без требования отслеживать эти изменения. []

Для MPI-1 вызовов конструкторов типов данных, аргументы-адреса в ФОРТРАНe имеют тип INTEGER. В новых вызовах MPI-2 аргументы-адреса имеют тип INTEGER(KIND=MPI_ADDRESS_KIND). Вызов MPI_TYPE_GET_CONTENTS возвращает все адреса аргументом типа INTEGER(KIND=MPI_ADDRESS_KIND). Это достоверно, даже если были использованы старые вызовы MPI-1. Таким образом, о расположении возвращенных значений можно судить по тому, как происходит связывание при возвратах в Си. Расположение также может быть определено исследованием новых вызовов MPI-2 в отношении к конструкторам типов данных обсуждаемых запросов MPI-1, которые включают адреса.

Объяснение: При наличии всех аргументов-адресов, возвращенных аргументом
array_of_addresses, результат расшифровки типа данных на Си и ФОРТРАНe будет получен в этом же аргументе. Полагают, что целое число типа INTEGER(KIND=MPI_ADDRESS_KIND) будет по крайней мере также велико, как и INTEGER аргумент, использованный при конструировании типа данных старыми запросами MPI-1, так что никакой потери информации не произойдет.

Далее приводятся определения значений, которые помещаются в каждое поле возвращаемых массивов в зависимости от конструктора, используемого для типа данных. Также указаны необходимые размеры массивов, которые являются значениями, возвращаемыми MPI_TYPE_GET_ENVELOPE. На ФОРТРАНe были сделаны следующие запросы:

INTEGER LARGE PARAMETER (LARGE = 1000) INTEGER TYPE, NI, NA, ND, COMBINER, I(LARGE), D(LARGE), IERROR INTEGER(KIND=MPI_ADDRESS_KIND) A(LARGE) ! КОНСТРУИРОВАНИЕ ТИПА DATATYPE (НЕ ПОКАЗАНО) CALL MPI_TYPE_GET_ENVELOPE(TYPE, NI, NA, ND, COMBINER, IERROR) IF ((N1 .GT. LARGE) .OR. (NA .GT. LARGE) .OR. & (ND .GT. LARGE)) THEN WRITE (*, *) "NI, NA, OR ND = ", N1, NA, ND, & " RETURNED BY MPI_TYPE_GET_ENVELOPE IS LARGER THAN LARGE = ", & LARGE CALL MPI_ABORT(MPI_COMM_WORLD, 99, IERROR) ENDIF CALL MPI_TYPE_GET_CONTENTS(TYPE, NI, NA, ND, I, A, D, IERROR)

Вариант аналогичного вызова на Си:

#define LARGE 1000 int ni, na, nd, combiner, i[LARGE]; MPI_Aint a[LARGE]; MPI_Datatype type, d[LARGE]; /* конструирование типа datatype (не показано) */ MPI_Type_get_envelope(type, ftni, &na, &nd, &combiner); if ((ni > LARGE) || (na > LARGE) || (nd > LARGE)) { fprintf (stderr, "ni, na, or nd = %d %d %d returned by ", ni, na, nd); fprintf(stderr, "MPI_Type_get_envelope is larger than LARGE = %d\n", LARGE); MPI_Abort(MPI_COMM_WORLD, 99); } MPI_Type_get_contents(type, ni, na, nd, i, a, d);

Код на С++ аналогичен приведенному выше коду на Си, с теми же возвращаемыми значениями. В описаниях, которые следуют ниже, используются имя аргументов из символов нижнего регистра. Если комбинер - это MPI_COMBINER_NAMED, то ошибочно вызывать MPI_TYPE_GET_CONTENTS.

Если комбинер - это MPI_COMBINER_DUP, то

Аргумент конструктора Расположение для Си и С++ Расположение для ФОРТРАНa  
oldtype d[0] D[1]  

и ni=0, na=0, nd=1.

Если комбинер - это MPI_COMBINER_CONTIGUOUS, то

Аргумент конструктора Расположение для Си и С++ Расположение для ФОРТРАНa  
count i[0] I[1]  
oldtype d[0] D[1]  

и ni=1, na=0, nd=1.

Если комбинер - это MPI_COMBINER_VECTOR, то

Аргумент конструктора Расположение для Си и С++ Расположение для ФОРТРАНa  
count i[0] I[1]  
blocklength i[1] I[2]  
stride i[2] I[3]  
oldtype d[0] D[1]  

и ni=3, na=0, nd=1.

Если комбинер - это MPI_COMBINER_HVECTOR_INTEGER или MPI_COMBINER_HVECTOR, то

Аргумент конструктора Расположение для Си и С++ Расположение для ФОРТРАНa  
count i[0] I[1]  
blocklength i[1] I[2]  
stride a[0] A[1]  
oldtype d[0] D[1]  

и ni=2, na=1, nd=1.

Если комбинер - это MPI_COMBINER_INDEXED, то

Аргумент конструктора Расположение для Си и С++ Расположение для ФОРТРАНa  
count i[0] I[1]  
array_of_blocklengths от i[1] до i[i[0]] от I(2) до I(I(1) + 1)  
array_of_displacements от i[i[0]+1] до i[2*i[0]] от I(I(l) + 2) до I(2*I(1) + 1)  
oldtype d[0] D[1]  

и ni=2*count+l, na=0, nd=1.

Если комбинер - это MPI_COMBINER_INDEXED_INTEGER или MPI_COMBINER_INDEXED, то

Аргумент конструктора Расположение для Си и С++ Расположение для ФОРТРАНa  
count i[0] I[1]  
array_of_blocklengths от i[1] до i[i[0]] от I(2) до I(I(1) + 1)  
array_of_displacements от a[0] до a[i[0] - 1] от A(1) до A(I(1))  
oldtype d[0] D[1]  

и ni=count+l, na=count, nd=1.

Если комбинер - это MPI_COMBINER_INDEXED_BLOCK, то

Аргумент конструктора Расположение для Си и С++ Расположение для ФОРТРАНa  
count i[0] I[1]  
blocklength i[1] I(2)  
array_of_displacements от i[2] до i[i[0] + 1] от I(3) до I(I(1) + 2)  
oldtype d[0] D(1)  

и ni=count+2, na=0, nd=1.

Если комбинер - это MPI_COMBINER_STRUCT_INTEGER или MPI_COMBINER_STRUCT, то

Аргумент конструктора Расположение для Си и С++ Расположение для ФОРТРАНa  
count i[0] I[1]  
array_of_blocklengths от i[1] до i[i[0]] от I(2) до I(I(1) + 1)  
array_of_displacements от a[0] до a[i[0] - 1] от A(1) до A(I(1))  
array_of_types от d[0] до d[i[0] - 1] от D(1) до D(I(1))  

и ni=count+1, na=count, nd=count.

Если комбинер - это MPI_COMBINER_STRUCT_INTEGER или MPI_COMBINER_STRUCT, то

Аргумент конструктора Расположение для Си и С++ Расположение для ФОРТРАНa  
ndims i[0] I[1]  
array_of_sizes от i[1] до i[i[0]] от I(2) до I(I(1) + 1)  
array_of_subsizes от i[i[0] + l] до i[2*i[0]] от I(I(l) + 2) до I(2*I(1) + 1)  
array_of_starts от i[2*i[0] + l] до i[3*i[0]] от I(2*I(l) + 2) до I(3*I(1) + 1)  
order i[3*i[0] I(3*I(l) + 2)  
oldtype d[0] D(1)  

и ni=3*ndims+2, na=0, nd=1.

Если комбинер - это MPI_COMBINER_DARRAY, то

Аргумент конструктора Расположение для Си и С++ Расположение для ФОРТРАНa  
size i[0] I[1]  
rank i[1] I[2]  
ndims i[2] I[3]  
array_of_gsizes от i[3] до i[i[2] + 2] от I(4) до I(I(3) + 3)  
array_of_distribs от i[i[2] + 3] до i[2*i[2]+2] от I(I(3) + 4) до I(2*I(3) + 3)  
array_of_dargs от i[2*i[2] + 3] до i[3*i[2] + 2] от I(2*I(3) + 4) до I(3*I(3) + 3)  
array_of_psizes от i[3*i[2] + 3] до i[4*i[2] + 2] от I(3*I(3) + 4) до I(4*I(3) + 3)  
order i[4*i[2] + 3] I(4*I(3) + 4)  
oldtype d[0] D(1)  

и ni=4*ndims+4, na=0, nd=1.

Если комбинер - это MPI_COMBINER_F90_REAL, то

Аргумент конструктора Расположение для Си и С++ Расположение для ФОРТРАНa  
p i[0] I[1]  
r i[1] I[2]  

и ni=2, na=0, nd=0.

Если комбинер - это MPI_COMBINER_F90_COMPLEX, то

Аргумент конструктора Расположение для Си и С++ Расположение для ФОРТРАНa  
p i[0] I[1]  
r i[1] I[2]  

и ni=2, na=0, nd=0.

Если комбинер - это MPI_COMBINER_F90_INTEGER, то

Аргумент конструктора Расположение для Си и С++ Расположение для ФОРТРАНa  
r i[0] I[1]  

и ni=1, na=0, nd=0.

Если комбинер - это MPI_COMBINER_RESIZED, то

Аргумент конструктора Расположение для Си и С++ Расположение для ФОРТРАНa  
lb a[0] A[1]  
extent a[1] A[2]  
oldtype d[0] D[1]  

и ni=0, na=2, nd=1.

Пример 6.2.

Этот пример показывает, как можно расшифровать тип данных. Подпрограмма printdatatype выводит элементы типа данных. Обратите внимание, что используется MPI_Type_free для типов данных, которые не предопределены.

/* * Пример расшифровки типа данных. Возвращается 0, если тип данных * предопределен, и 1, в противном случае. */ #include <stdio.h> #include <stdlib.h> #include "mpi.h"

int printdatatype(MPI_Datatype datatype) { int *array_of_ints; MPI_Aint *array_of_adds; MPI_Datatype *array_of_dtypes; int num_ints, num_adds, num_dtypes, combiner; int i; MPI_Type_get_envelope(datatype, &num_ints, &num_adds, &num_dtypes, ftcombiner);

switch(combiner) { case MPI_COMBINER_NAMED: printf( "Datatype is named:" ); /* В принципе, вывод здесь может быть организован по разному. Можно применяться MPI_TYPE_GET_NAME, если предпочтительно использовать имена, которые пользовать мог изменить. */ if (datatype == MPI_INT) { printf( "MPI_INT\n" ); } else if (datatype == MPI_DOUBLE) { printf("MPI_DOUBLE\n" ); } else if (...) { ... } else { test for other types ... } return 0; break; case MPI_COMBINER_STRUCT: case MPI_COMBINER_STRUCT_INTEGER: printf("Datatype is struct containing"); array_of_ints = (int *)malloc(num_ints * sizeof(int)); array_of_adds = (MPI_Aint *)malloc(num_adds * sizeof(MPI_Aint)); array_of_dtypes = (MPI_Datatype *) malloc(num_dtypes * sizeof(MPI_Datatype)); MPI_Type_get_contents(datatype, num_ints, num_adds, num_dtypes, array_of_ints, array_of_adds, array_of_dtypes); printf ("%d datatypes: \n", array_of _ints [0]); for (i=0; i<array_of_ints[0]; i++) { printf("blocklength %d, displacement %ld, type:\n", array_of_ints[i+1], array_of_adds[i]); if (printdatatype(array_of_dtypes[i])) { /* Обратите внимание, что тип тип освобождается */ /* ТОЛЬКО если он не предопределен */ MPI_Type_free(&array_of_dtypes[i]); } } free(array_of_ints); free(array_of_adds); free(array_of_dtypes); break; . . . другие величины комбинера . . . default : printf( "Unrecognized combiner type\n" ); } return 1; }


next up previous contents
Next: MPI и треды Up: Внешние интерфейсы Previous: Классы ошибок, коды ошибок   Contents
Alex Otwagin 2002-12-10