MPI-1 предоставляет несколько типов данных, соответствующих встроенным типам данных, поддерживаемым Си и ФОРТРАН. Они включают MPI_INTEGER, MPI_REAL, MPI_INT, MPI_DOUBLE, и т.д, а также необязательные типы MPI_REAL4, MPI_REAL8, и т.д. При этом существует однозначное соответствие между описанием языка и типом MPI.
ФОРТРАН (начиная с ФОРТРАН90) предоставляет так называемые KIND-параметризованные типы. Эти типы объявлены с использованием встроенного
типа (INTEGER, REAL, COMPLEX, LOGICAL или CHARACTER) с необязательным целым KIND параметром, который выбирает из
одного или более вариантов. Конкретное значение различных значений KIND
зависит от реализации и не определяется языком. ФОРТРАН предоставляет функии
выбора KIND selected_real_kind для типов REAL и COMPLEX, и selected_int_kind для типов INTEGER, которые позволяют
пользователю объявлять переменные с минимальной точностью или количеством
разрядов. Эти функции предоставляют переносимый способ объявления KIND-параметризованных переменных REAL, COMPLEX
и INTEGER в ФОРТРАН. Эта схема обратно совместима с ФОРТРАН77.
Переменные REAL и INTEGER в ФОРТРАН имеют KIND по
умолчанию, если он не определен. Переменные DOUBLE PRECISION
имеют встроенный тип REAL с нестандартным KIND. Эти два объявления
эквивалентны:
double precision x
real(KIND(0.0d0)) x
MPI предоставляет два различных метода использования встроенных числовых типов. Первый метод может быть использован когда переменные объявлены в переносимом виде - используя KIND по умолчанию или используя параметры KIND, полученные функциями selected_int_kind или selected_real_kind. С этим методом, MPI автоматически выбирает необходимый тип данных (например, 4 или 8 байт) и предоставляет преобразование представления в гетерогенных средах. Второй метод дает пользователю полное управление над коммуникациями, раскрывая машинные представления.
Параметризованные типы данных с определенной точностью и диапазоном экспоненты.
MPI-1 предоставляет типы данных, соответствующие стандартным типам данных ФОРТРАН77 - MPI_INTEGER, MPI_COMPLEX, MPI_REAL, MPI_DOUBLE_PRECISION и MPI_DOUBLE_COMPLEX. MPI автоматически выбирает правильный размер данных и предоставляет преобразование представления в гетерогенных средах. Механизм, описанный в этой главе, расширяет модель MPI-1 для поддержки переносимых параметризованных типов данных.
Модель для поддержки переносимых параметризованных типов такова: переменные REAL объявлены (возможно, неявно), с использованием selected_real_kind(p, r) для определения параметра KIND, p - десятичная разрядная точность, а r - диапазон экспоненты. MPI неявно поддерживает двумерный массив определенных типов данных MPI D(p, r). D(p, r) определен для каждого значения (p, r), поддерживаемого компилятором, включая пары, в которых одно из значений не определено. Попытка доступа к элементу массива с индексом (p, r) не поддерживаемым компилятором ошибочны. MPI неявно поддерживает такой же массив типов данных COMPLEX. Такой же массив для целых чисел относится к selected_int_kind и индексируется по требуемому количеству разрядов r. Заметьте, что типы данных, содержащиеся в этих массивах не те же, что типы MPI вроде MPI_REAL, и т.д., а новый набор.
Совет разработчикам: Вышеуказанное описание дано только в описательных целях. Разработчики не обязаны создавать подобные внутренние массивы.[]
Совет пользователям: selected_real_kind() отражает большое число пар (p,r) в намного меньшее число параметров KIND, поддерживаемых компилятором. Параметры KIND не определены языком и не переносимы. С точки зрения языка, встроенные типы с одним и тем же базовым типом и параметром KIND одинаковы. Для того, чтобы позволить работу в гетерогенных средах, понятия MPI более строги. Соответствующие типы данных MPI совпадают тогда и только тогда, когда они имеют то же значение (p,r) ( REAL и COMPLEX) или значение r (INTEGER). Поэтому MPI имеет большее количество типов, чем количество фундаментальных типов в языках.
MPI_TYPE_CREATE_F90_REAL(p, r, newtype) | |||
IN | p | точность в десятичных разрядах (целое число) | |
IN | r | десятичный диапазон экспоненты (целое число) | |
OUT | newtype | требуемый тип данных MPI (дескриптор) |
int MPI_Type_create_f90_real(int p, int r, MPI_Datatype *newtype)
MPI_TYPE_CREATE_F90_REAL(P, R, NEWTYPE, IERROR)
INTEGER P, R, NEWTYPE, IERROR
static MPI::Datatype MPI::Datatype::Create_f90_real(int p, int r)
Эта функция возвращает тип MPI, который соответствует переменной
REAL типа
KIND selected_real_kind(p, r). В описанной
выше модели она возвращает дескриптор элемента D(p, r). p
или r могут быть убраны из вызовов selected_real_kind(p,
r) (но не оба). Аналогично, p или r могут быть установлены в MPI_UNDEFINED. В коммуникации тип MPI A, возвращенный
MPI_TYPE_CREATE_F90_REAL, соответствует типу B
тогда и только тогда, когда B был возвращен функцией MPI_TYPE_CREATE_F90_REAL вызванной с теми же параметрами
p и r или если B - дубликат такого типа данных.
Ограничения по использованию возращенного типа данных с представлением данных
``external32
'' даны далее.
Значения p и r, не поддерживаемые компилятором, вызывают ошибку.
MPI_TYPE_CREATE_F90_COMPLEX(p, r, newtype) | |||
IN | p | точность в десятичных разрядах (целое число) | |
IN | r | десятичный диапазон экспоненты (целое число) | |
OUT | newtype | требуемый тип данных MPI (дескриптор) |
int MPI_Type_create_f90_complex(int p, int r, MPI_Datatype *newtype)
MPI_TYPE_CREATE_F90_COMPLEX(P, R, NEWTYPE, IERROR)
INTEGER P, R, NEWTYPE, IERROR
static MPI::Datatype MPI::Datatype::Create_f90_complex(int p, int r)
Эта функция возвращает тип MPI, который соответствует переменной
COMPLEX типа
KIND selected_real_kind(p, r). p
или r могут быть убраны из вызовов selected_real_kind(p,
r) (но не оба). Аналогично, p или r могут быть установлены в MPI_UNDEFINED. Правила соответствия для созданных типов данных аналогичны
правилам для MPI_TYPE_CREATE_F90_REAL. Ограничения по использованию
возвращенного типа данных с представлением данных ``external32
'' даны
далее.
Значения p и r, не поддерживаемые компилятором, вызывают ошибку.
MPI_TYPE_CREATE_F90_INTEGER(r, newtype) | |||
IN | r | десятичный диапазон экспоненты - т.е. количество десятичных разрядов (целое число) | |
OUT | newtype | требуемый тип данных MPI (дескриптор) |
int MPI_Type_create_f90_integer(int r, MPI_Datatype *newtype)
MPI_TYPE_CREATE_F90_INTEGER(R, NEWTYPE, IERROR)
INTEGER R, NEWTYPE, IERROR
static MPI::Datatype MPI::Datatype::Create_f90_integer(int r)
Эта функция возвращает тип данных MPI, который соответствует переменной
INTEGER типа KIND
selected_int_kind(r). Правила соответствия для созданных типов данных
аналогичны правилам для MPI_TYPE_CREATE_F90_REAL. Ограничения по
использованию возращенного типа данных с представлением данных
``external32
'' даны далее.
Значения p и r, не поддерживаемые компилятором, вызывают ошибку.
Пример 8.11 Иллюстрирует как создать типы данных MPI, соответствующие
двум типам ФОРТРАНa, описанным при помощи selected_int_kind и selected_real_kind
integer longtype, quadtype
integer, parameter :: long = selected_int_kind(15)
integer(long) ii(10)
real(selected_real_kind(30)) x(10)
call MPI_TYPE_CREATE_F90_INTEGER(15, longtype, ierror)
call MPI_TYPE_CREATE_F90_REAL(30, MPI_UNDEFINED, quadtype, ierror)
...
call MPI_SEND(ii, 10, longtype, ...)
call MPI_SEND(x, 10, quadtype, ...)
Совет пользователям: Типы данных, полученные от функций выше - предопределенные типы данных. Они не могут быть освобождены; они не обязаны создаваться; они могут быть использованы с предопределенными операциями понижения точности. Есть две ситуации, в которых они ведут себя синтаксически, но не семантически отличаясь от предопределенных типов данных MPI:
Объяснение: Интерфейс MPI_TYPE_CREATE_F90_REAL/COMPLEX/INTEGER требует на входе оригинальные значения диапазона и точности, чтобы определить полезные и независимые от компилятора (глава 7.5.2) или определенные пользователем (глава 7.5.3) представления данных, и в целях получения возможности производить автоматические и эффективные преобразования данных в гетерогенной среде.[]
Типы данных и представление ``external32
''.
Теперь мы определим, как типы данных, описанные в этой главе, ведут себя,
если они использованы с внешним представлением данных
``external32
'', описанным в главе 7.5.2.
Представление ``external32
'' определяет форматы данных для целых значений
и значений с плавающей точкой. Целые числа представлены по модулю два в формате
``big-endian''. Числа с плавающей точкой представлены в одном из форматов IEEE.
IEEE определяет форматы ``Single'', ``Double'' и ``Double Extended'',
требующие соответственно 4, 8 и 16 байт памяти. Для формата IEEE ``Double
Extended'' MPI определяет ширину формата 16 байт с 15 битами
экспоненты, диапазоном +10383, 112 бит мантиссы и кодировку, аналогичную формату
``Double''.
Представления external32
типов, возвращенных MPI_TYPE_CREATE_F90_REAL/COMPLEX/INTEGER даны в соответствии со следующими
правилами:
Для MPI_TYPE_CREATE_F90_REAL:
if (p > 33) or (r > 4931) then представление external32
не определено
else if (p > 15) or (r > 307) then external32_size = 16
else if (p > 6) or (r > 37) then external32_size = 8
else external32_size = 4
Для MPI_TYPE_CREATE_F90_COMPLEX: размер вдвое больше чем MPI_TYPE_CREATE_F90_REAL.
Для MPI_TYPE_CREATE_F90_INTEGER:
if (r > 38) then представление external32
не определено
else if (r > 18) then external32_size = 16
else if (r > 9) then external32_size = 8
else if (r > 4) then external32_size = 4
else if (r > 2) then external32_size = 2
else external32_size = 1
Если представление типа данных ``external32
'' не определено, его
использования прямо или косвенно (как часть другого типа или с помощью дубля) в
операциях, требующих ``external32
'' тоже не определено. Эти операции
включают в себя MPI_PACK_EXTERNAL, MPI_UNPACK_EXTERNAL и множество
функций MPI_FILE, где используется ``external32
''. Диапазоны, для
которых представление ``external32
'' не определено, зарезервированы
для дальнейшей стандартизации.
Поддержка типов данных с определенным размером. MPI-1 предоставляет поименованные типы данных, соответствующие опциональным типам ФОРТРАН77, содержащим явную длину - MPI_REAL4, MPI_INTEGER8, и др. Эта глава описывает механизм, обобщающий эту модель для поддержки всех встроенных числовых типов данных ФОРТРАНa.
Мы предполагаем, что каждый класс типов (integer, real, complex) и каждый размер слова имеет уникальное машинное представление. Для каждой пары (класс типа, n) поддерживаемой компилятором, MPI должен предоставить поименованный тип данных соответствующего размера. Имя этого типа должно быть в форме MPI_<тип>n для Си и ФОРТРАНa и в форме MPI::<тип>n для С++, где <тип> - REAL, INTEGER или COMPLEX, а n - длина машинного представления в байтах. Этот тип локально соответствует всем переменным типа (тип класса, n). Список имен для таких типов включает:
MPI_REAL4 | MPI_INTEGER1 |
MPI_REAL8 | MPI_INTEGER2 |
MPI_REAL16 | MPI_INTEGER4 |
MPI_COMPLEX8 | MPI_INTEGER8 |
MPI_COMPLEX16 | MPI_INTEGER16 |
MPI_COMPLEX32 |
В MPI-1 эти типы опциональны и соответствуют нестандартным определениям, поддерживаемым многими компиляторами ФОРТРАНa. В MPI-2 для каждого представления, поддерживаемого компилятором, необходим один тип. Для обратной совместимости с интерпретацией этих типов в MPI-1, мы предполагаем что нестандартные объявления REAL*n, INTEGER*n, всегда создают переменную, чье представление имеет размер n. Все эти типы предопределены.
Дополнительные размеры с нестандартным размером, например MPI_LOGICAL1 (соответствующий LOGICAL*1) могут быть определены в реализациях, но не требуются стандартом MPI.
Следующие функции позволяют пользователю получить требуемый тип данных встроенного типа языка ФОРТРАН.
MPI_SIZEOF(x, size) | |||
IN | x | переменная ФОРТРАН встроенного числового типа (выбор) | |
OUT | size | размер машинного представления (целое число) |
MPI_SIZEOF(X, SIZE, IERROR)
<type> X
INTEGER SIZE, IERROR
Эта функция возвращает размер машинного представления переменной в байтах. Это функция ФОРТРАН и имеет привязку только для ФОРТРАН.
Совет пользователям: Эта функция похожа на оператор sizeof для Си и С++, но немного отличается. Если ей будет передан массив, она вернет размер базового элемента, а не всего массива. []
Объяснение: Эта функция недоступна в других языках за ненадобностью.[]
MPI_TYPE_MATCH_SIZE(typeclass, size, type) | |||
IN | typeclass | общий тип (целое число) | |
IN | size | размер представления в байтах (целое число) | |
OUT | type | тип данных правильного размера (дескриптор) |
int MPI_Type_match_size(int typeclass, int size, MPI_Datatype *type)
MPI_TYPE_MATCH_SIZE(TYPECLASS, SIZE, TYPE, IERROR)
INTEGER TYPECLASS, SIZE, TYPE, IERROR
static MPI::Datatype MPI::Datatype::Match_size(int typeclass, int size)
typeclass - MPI_TYPECLASS_REAL, MPI_TYPECLASS_INTEGER или MPI_TYPECLASS_COMPLEX, в соответствии с желаемым типом. Функция возвращает тип данных MPI, соответствующий локальной переменной типа (тип класса, размер).
Эта функция возвращает ссылку (дескриптор) на один из типов данных, не являющийся копией. Этот тип не может быть освобожден. Функция MPI_TYPE_MATCH_SIZE может быть использована для для получения типа с определенным размером, соответствующего встроенному числовому типу ФОРТРАНa путем вызова MPI_SIZEOF для нахождения размера переменной, с последующим вызовом MPI_TYPE_MATCH_SIZE для поиска подходящего типа. В Си и С++ вместо MPI_SIZEOF можно использовать функцию sizeof(). Кроме того, для переменных с KIND по умолчанию, размер можно вычислить вызовом MPI_TYPE_GET_EXTENT, если известен typeclass. Использование размера, не поддерживаемого компилятором вызывает ошибку.
Объяснение: Это - функция ``для удобства''. Без нее поиск необходимого именованного типа может быть утомительным. (см. комментарии для разработчиков).[]
Совет разработчикам: Эта функция может быть реализована
как серия тестов:
int MPI_Type_match_size(int typeclass, int size,
MPI_Datatype *rtype)
{
switch(typeclass) {
case MPI_TYPECLASS_REAL: switch(size) {
case 4: *rtype = MPI_REAL4; return MPI_SUCCESS;
case 8: *rtype = MPI_REAL8; return MPI_SUCCESS;
default: error(...);
}
case MPI_TYPECLASS_INTEGER: switch(size) {
case 4: *rtype = MPI_INTEGER4; return MPI_SUCCESS;
case 8: *rtype = MPI_INTEGER8; return MPI_SUCCESS;
default: error(...); }
... etc ...
}
}
Связь с использованием разных типов. Обычные правила соответствия типов справедливы и для типов с определенным размером: значение, посланное с типом MPI_<тип>n может быть получено другим процессом с таким же типом. Большинство современных компьютеров использует дополнение двойки для целых и формат IEEE для плавающей точки. Поэтому, связь с использованием таких типов не выльется в потерю точности или ошибки округления.
Совет пользователям: При работе
в гетерогенных окружениях нужна осторожность. Пример:
real(selected_real_kind(5)) x(100)
call MPI_SIZEOF(x, size, ierror)
call MPI_TYPE_MATCH_SIZE(MPI_TYPECLASS_REAL, size, xtype, ierror)
if (myrank .eq. 0) then
... initialize x ...
call MPI_SEND(x, xtype, 100, 1, ...)
else if (myrank .eq. 1) then
call MPI_RECV(x, xtype, 100, 0, ...)
endif
Это может не работать в гетерогенной среде, если размер size различается в
процессах 1 и 0. В гомогенной среде проблемы быть не должно. Для связи в
гетерогенной среде есть, как минимум, четыре варианта, если не используется
нестандартные объявления заданного размера - как REAL*8.
Первое - определить переменные типа по умолчанию и использовать для них типы
MPI - например, переменная типа REAL и использовать MPI_REAL. Второй - использовать selected_real_kind
или selected_int_kind и с функциями из предыдущей главы. Третье -
определить переменную, которая будет одинакова во всех архитектурах (например,
selected_real_kind(12) почти во всех компиляторах будет размером 8
байт). Четвертый - аккуратно проверить размер машинного представления до связи.
Это может потребовать явного преобразования в переменную, размер которой походит
для связи, и согласование размера между приемником и передатчиком.
Также заметьте, что использование ``external32
'' для ввода-вывода требует
пристального внимания к размерам представлений. Пример:
real(selected_real_kind(5)) x(100)
call MPI_SIZEOF(x, size, ierror)
call MPI_TYPE_MATCH_SIZE(MPI_TYPECLASS_REAL, size, xtype, ierror)
if (myrank .eq. 0) then
call MPI_FILE_OPEN(MPI_COMM_SELF, 'foo', &
MPI_MODE_CREATE+MPI_MODE_WRONLY, &
MPI_INFO_NULL, fh, ierror)
call MPI_FILE_SET_VIEW(fh, 0, xtype, xtype, 'external32', &
MPI_INFO_NULL, ierror)
call MPI_FILE_WRITE(fh, x, 100, xtype, status, ierror)
call MPI_FILE_CLOSE(fh, ierror)
endif
call MPI_BARRIER(MPI_COMM_WORLD, ierror)
if (myrank .eq. 1) then
call MPI_FILE_OPEN(MPI_COMM_SELF, 'foo', MPI_MODE_RDONLY, &
MPI_INFO_NULL, fh, ierror)
call MPI_FILE_SET_VIEW(fh, 0, xtype, xtype, 'external32', &
MPI_INFO_NULL, ierror)
call MPI_FILE_WRITE(fh, x, 100, xtype, status, ierror)
call MPI_FILE_CLOSE(fh, ierror)
endif
Если процессы 0 и 1 работают на разных машинах, код может работать не так, как ожидается, если size на этих машинах имеет разное значение.[] --
--