next up previous contents
Next: Новые стандартные типы Up: Новые функции манипуляции типами Previous: Конструктор типа данных ``субмассив''   Contents

Конструктор типа данных ``распределенный массив''

Конструктор распределенного массива поддерживает распределения данных, сходные с 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 был корректным, должно выполняться условие $\prod_{i=0}^{ndims-1}array\_of\_psizes[i] = size$. Порядок процессов в сетке процессов считается с главной строкой, как и в случае топологий виртуальных 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 имеет форму

$\{(type_0,disp_0),(type_1,disp_1),...,(type_{n-1},disp{n-1})\}$

где $type_i$ - стандартный тип MPI, и пусть ex будет длиной oldtype.

С учетом вышеуказанного, функция cyclic() определяется так:

cyclic(darg,gsize,r,psize,oldtype)
= {(MPI_LB,0),
$(type_0,disp_0+r\times darg\times ex),...,$
$(type_{n-1},disp_{n-1}+r\times darg\times ex),$
$(type_0,disp_0+(r\times darg+1)\times ex),...,$
$(type_{n-1},disp_{n-1}+(r\times darg+1)\times ex),$
...
$(type_0,disp_0+((r+1)\times darg-1)\times ex),...,$
$(type_{n-1},disp_{n-1}+((r+1)\times darg-1)\times ex),$
...
$(type_0,disp_0+r\times darg\times ex+psize\times darg\times ex),...,$
$(type_{n-1},disp_{n-1}+r\times darg\times ex+psize\times darg\times ex),$
$(type_0,disp_0+(r\times darg+1)\times ex+psize\times darg\times ex),...,$
$(type_{n-1},disp_{n-1}+(r\times darg+1)\times ex+psize\times darg\times ex),$
...
$(type_0,disp_0+((r+1)\times darg-1)\times ex+psize\times darg\times ex),...,$
$(type_{n-1},disp_{n-1}+((r+1)\times darg-1)\times ex+psize\times darg\times ex),$
...
$(type_0,disp_0+r\times darg\times ex+psize\times darg\times ex\times(count-1)),...,$
$(type_{n-1},disp_{n-1}+r\times darg\times ex+psize\times darg\times ex\times(count-1)),$
$(type_0,disp_0+(r\times darg+1)\times ex+psize\times darg\times ex\times(count-1)),...,$
$(type_{n-1},disp_{n-1}+(r\times darg+1)\times ex+psize\times darg\times ex\times(count-1)),$
...
$(type_0,disp_0+(r\times darg-1+darg_{last}-1)\times ex+psize\times darg\times ex\times(count-1)),...,$
$(type_{n-1},disp_{n-1}+(r\times darg+darg_{last}-1)\times ex+psize\times darg\times ex\times(count-1)),$
(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 - число блоков, которые должны быть распределены между процессорами. И, в конце концов, $darg_{last}$ определяется следующим фрагментом: 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)


next up previous contents
Next: Новые стандартные типы Up: Новые функции манипуляции типами Previous: Конструктор типа данных ``субмассив''   Contents
Alex Otwagin 2002-12-10