Конструктор распределенного массива поддерживает распределения данных, сходные с HPF[12]. Кроме этого, в отличие от HPF, порядок хранения может быть задан как для массивов Си, так и для ФОРТРАНА.
Совет пользователям: Вы можете создать HPF-подобный образ файла, используя этот конструктор типа описанным образом. Дополнительные типы файлов создаются групповым вызовом каждым процессом с идентичными аргументами (за исключением ранга, который должен быть установлен соответствующим образом). Эти типы файлов (с идентичными disp и etype) используются затем для определения отображения файла (через MPI_FILE_SET_VIEW). Используя это отображение, совместная операция доступа к данным (с идентичными смещениями) даст HPF-подобный шаблон распределения. []
MPI_TYPE_CREATE_DARRAY(size, rank, ndims, array_of_gsizes,
array_of_distribs, array_of_dargs,
array_of_psizes, order, oldtype, newtype)
IN | size | размер группы процессов (положительное целое) | |
IN | rank | ранг в группе процессов (неотрицательное целое) | |
IN | ndims | число измерений масива и размеры сетки процессов (положительное целое) | |
IN | array_of_gsizes | число элементов типа oldtype в каждом измерении глобального массива (массив положительных целых) | |
IN | array_of_distribs | распределение массива в каждом измерении (массив состояний) | |
IN | array_of_dargs | аргумент распределения в каждом измерении (массив положительных целых) | |
IN | array_of_psizes | размер сетки процессов в каждом измерении (массив положительных целых) | |
IN | order | порядок зранения массива (состояние) | |
IN | oldtype | старый тип данных (дескриптор) | |
OUT | newtype | новый тип данных (дескриптор) |
int MPI_Type_create_darray(int size, int rank, int ndims, int
array_of_gsizes[], int array_of_distribs[],
int array_of_dargs[], int array_of_psizes[], int order,
MPI_Datatype oldtype, MPI_Datatype *newtype)
MPI_TYPE_CREATE_DARRAY(SIZE, RANK, NDIMS, ARRAY_OF_GSIZES,
ARRAY_OF_DISTRIBS, ARRAY_OF_DARGS, ARRAY_OF_PSIZES, ORDER,
OLDTYPE, NEWTYPE, IERROR)
INTEGER SIZE, RANK, NDIMS, ARRAY_OF_GSIZES(*),
ARRAY_OF_DISTRIBS(*), ARRAY_OF_DARGS(*), ARRAY_OF_PSIZES(*),
ORDER, OLDTYPE, NEWTYPE, IERROR
MPI::Datatype MPI::Datatype::Create_darray(int size, int rank,
int ndims, const int array_of_gsizes[],
const int array_of_distribs[], const int array_of_dargs[],
const int array_of_psizes[], int order) const
MPI_TYPE_CREATE_DARRAY может быть использована для создания типов данных, соответствующих распределению ndims-мерного массива элементов типа oldtype в ndims-мерную сетку логических процессов. Неиспользуемые измерения array_of_psizes должны быть установлены в 1. (См. пример Distributed Array Datatype Constructor .) Чтобы вызов MPI_TYPE_CREATE_DARRAY был корректным, должно выполняться условие . Порядок процессов в сетке процессов считается с главной строкой, как и в случае топологий виртуальных Cartesian процессов в MPI-1.
Совет пользователям: Для массивов и ФОРТРАНА и Си, порядок процессов считается построчно. Это соответствует порядку, используемому в случае виртуальных декартовых процессов в MPI-1. Для создания таких виртуальных топологий процессов или для нахождения координат процесса в сетке процессов и т.д., пользователи могут использовать соответствующие функции из MPI-1. []
Каждое измерение в массиве может распределяться одним из трех способов:
Константа MPI_DISTRIBUTE_DFLT_DARG определяет аргумент распределения по умолчанию. Аргумент не распределенного измерения игнорируется. Для любого измеренияi, в котором распределение равно MPI_DISTRIBUTE_BLOCK, ошибочно определять array_of_dargs[i] * array_of_psizes[i] < array_of_gsizes[i].
Например, вид HPF ARRAY(CYCLIC(15)) соответствует MPI_DISTRIBUTE_CYCLIC с аргументом 15, а вид HPF ARRAY(BLOCK)
соответствует MPI_DISTRIBUTE_BLOCK с агрументом распределения
MPI_DISTRIBUTE_DFLT_DARG.
Аргумент order используется как и в MPI_TYPE_CREATE_SUBARRAY для определения порядка размещения. Поэтому, массивы, описанные этим конструктором типа могут быть сохранены в порядке ФОРТРАНА (по колонкам) или Си (построчно). Допустимые значения для order - MPI_ORDER_FORTRAN и MPI_ORDER_C.
Эта функция создает новый тип данных MPI с картой типа, определенной в терминах функции ``cyclic()'' (см. ниже).
Без потери общности достаточно определить карту типа для случая MPI_DISTRIBUTE_CYCLIC, где не используется MPI_DISTRIBUTE_DFLT_DARG.
MPI_DISTRIBUTE_BLOCK и MPI_DISTRIBUTE_NONE могут быть
сокращены до случая
MPI_DISTRIBUTE_CYCLIC для измерения i следующим образом.
MPI_DISTRIBUTE_BLOCK с array_of_dargs[i] равным MPI_DISTRIBUTE_DFLT_DARG эквивалентен
MPI_DISTRIBUTE_CYCLIC с array_of_dargs[i] установленным в
(mpiargarray_of_gsizes[i] + mpiargarray_of_psizes[i] - 1) / mpiargarray_of_psizes[i].
Если array_of_dargs[i] - не MPI_DISTRIBUTE_DFLT_DARG, то MPI_DISTRIBUTE_BLOCK и
MPI_DISTRIBUTE_CYCLIC эквивалентны.
MPI_DISTRIBUTE_NONE эквивалентен MPI_DISTRIBUTE_CYCLIC с array_of_dargs[i] установленным в array_of_gsizes[i].
И, в конце концов, MPI_DISTRIBUTE_CYCLIC с array_of_dargs[i] равным MPI_DISTRIBUTE_DFLT_DARG эквивалентен MPI_DISTRIBUTE_CYCLIC с array_of_dargs[i] установленным в 1.
Для MPI_ORDER_FORTRAN, ndims-мерный распределенный массив
(newtype) определяется следущим фрагментом кода:
oldtype[0] = oldtype;
for ( i = 0; i < ndims; i++ ) {
oldtype[i+1] = cyclic(array_of_dargs[i],
array_of_gsizes[i],
r[i],
array_of_psizes[i],
oldtype[i]);
}
newtype = oldtype[ndims];
Код для MPI_ORDER_C:
oldtype[0] = oldtype;
for ( i = 0; i < ndims; i++ ) {
oldtype[i + 1] = cyclic(array_of_dargs[ndims - i - 1],
array_of_gsizes[ndims - i - 1],
r[ndims - i - 1],
array_of_psizes[ndims - i - 1],
oldtype[i]);
}
newtype = oldtype[ndims];
где r[i] - позиция процесса (с рангом rank) в сетке процессов на
измерении i. Значения r[i] даны следующим фрагментом кода:
t_rank = rank;
t_size = 1;
for (i = 0; i < ndims; i++)
t_size *= array_of_psizes[i];
for (i = 0; i < ndims; i++) {
t_size = t_size / array_of_psizes[i];
r[i] = t_rank / t_size;
t_rank = t_rank % t_size;
}
Пусть карта типа oldtype имеет форму
где - стандартный тип MPI, и пусть ex будет длиной oldtype.
С учетом вышеуказанного, функция cyclic() определяется так:
cyclic(darg,gsize,r,psize,oldtype)
= {(MPI_LB,0),
...
...
...
...
...
(MPI_UB,gsize*ex)}
где count определяется следущим фрагментом кода:
nblocks = (gsize + (darg - 1)) / darg;
count = nblocks / psize;
left_over = nblocks - count * psize;
if (r < left_over)
count = count + 1;
Здесь nblocks - число блоков, которые должны быть распределены между
процессорами. И, в конце концов, определяется следующим
фрагментом:
if ((num_in_last_cyclic = gsize % (psize * darg)) == 0)
darg_last = darg;
else
darg_last = num_in_last_cyclic - darg * r;
if (darg_last < darg)
darg_last = darg;
if (darg_last <= 0)
darg_last = darg;
Пример Сгенерируем типы файлов в соответствии с распределением HPF:
<oldtype> FILEARRAY(100, 200, 300)
!HPF$ PROCESSORS PROCESSES(2, 3)
!HPF$ DISTRIBUTE FILEARRAY(CYCLIC(10), *, BLOCK) ONTO PROCESSES
Предполагая, что подключены шесть процессоров, этого можно достичь следующим
кодом на ФОРТРАН:
ndims = 3
array_of_gsizes(1) = 100
array_of_distribs(1) = MPI_DISTRIBUTE_CYCLIC
array_of_dargs(1) = 10
array_of_gsizes(2) = 200
array_of_distribs(2) = MPI_DISTRIBUTE_NONE
array_of_dargs(2) = 0
array_of_gsizes(3) = 300
array_of_distribs(3) = MPI_DISTRIBUTE_BLOCK
array_of_dargs(3) = MPI_DISTRIBUTE_DFLT_ARG
array_of_psizes(1) = 2
array_of_psizes(2) = 1
array_of_psizes(3) = 3
call MPI_COMM_SIZE(MPI_COMM_WORLD, size, ierr)
call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr)
call MPI_TYPE_CREATE_DARRAY(size, rank, ndims, &
array_of_gsizes, array_of_distribs, array_of_dargs, &
array_of_psizes, MPI_ORDER_FORTRAN, oldtype, newtype,&
ierr)