next up previous contents
Next: Операции, определяемые пользователем Up: Глобальные операции редукции Previous: Предопределенные операции редукции   Contents

MINLOС и MAXLOС

Оператор MPI_MINLOC используется для расчета глобального минимума и соответствующего ему индекса. MPI_MAXLOC аналогично считает глобальный максимум и индекс. Одно из применений этих операций - вычисление глобального минимума (максимума) и номера процесса, содержащего это значение.

Операция, которая определяет MPI_MAXLOC , такова:


\begin{displaymath}
\left({{\begin{array}{*{20}c}
u \hfill \\
i \hfill \\
\e...
...ay}{*{20}c}
w \hfill \\
k \hfill \\
\end{array} }} \right)
\end{displaymath}

где w = max(u, v) и


\begin{displaymath}
k = \left\{ {{\begin{array}{*{20}c}
i \hfill \\
{\min (i,...
... \hfill\\
{\mbox{if u } < \mbox{ v}} \hfill\\
\end{array} }
\end{displaymath}

MPI_MINLOC определен аналогично:


\begin{displaymath}
\left({{\begin{array}{*{20}c}
u \hfill \\
i \hfill \\
\e...
...ay}{*{20}c}
w \hfill \\
k \hfill \\
\end{array} }} \right)
\end{displaymath}

где w = min(u, v) и


\begin{displaymath}
k = \left\{ {{\begin{array}{*{20}c}
i \hfill \\
{\min (i,...
... \hfill\\
{\mbox{if u } < \mbox{ v}} \hfill\\
\end{array} }
\end{displaymath}

Обе операции ассоциативны и коммутативны. Отметим, что если MPI_MAXLOC применяется для последовательности пар (u$_{0}$, 0), (u$_{1}$, 1), ..., (u$_{n - 1}$, n-1), то возвращаемое значение есть (u, r), где u=max$_{i}$(u$_{i})$ и r - индекс первого глобального максимума в последовательности. Таким образом, если каждый процесс предоставляет значение и свой номер в группе, тогда операция редукции с op = MPI_MAXLOC возвратит значение максимума и номер первого процесса с этим значением. Аналогично, MPI_MINLOC может быть использована для получения минимума и его индекса. В общем, MPI_MINLOC вычисляет лексикографический минимум , где элементы упорядочены согласно первому компоненту каждой пары, и отношение разрешается согласно второму компоненту.

Операция редукции определена для работы с аргументами, содержащими пару: значение и индекс. Как в языке ФОРТРАН , так и для языка Си имеются типы данных для описания этой пары. Потенциально смешанная природа таких параметров является проблемой для языка ФОРТРАН. Для языка ФОРТРАН проблема обойдена благодаря наличию в MPI типа, состоящего из пары того же типа, что и значение, и присоединенного к этому типу индекса. Для языка Си MPI предоставляет парный тип, части которого имеют различный тип и индекс имеет тип int .

Чтобы использовать MPI_MINLOC и MPI_MAXLOC в операции редукции, нужно обеспечить аргумент datatype, который представляет пару (значение и индекс). MPI предоставляет девять таких предопределенных типов данных. Операции MPI_MAXLOC и MPI_MINLOC могут быть использованы со следующими типами данных:

ФОРТРАН:
Название Описание
MPI_2REAL пара переменных типа REAL
MPI_2DOUBLE_PRECISION пара переменных типа DOUBLE PRECISION
MPI_2INTEGER пара переменных типа INTEGER
Си:
Название Описание
MPI_FLOAT_INT переменные типа float и int
MPI_DOUBLE_INT переменные типа double и int
MPI_LONG_INT переменные типа long и int
MPI_2INT пара переменных типа int
MPI_SHORT_INT переменные типа short и int
MPI_LONG_DOUBLE_INT переменные типа long double и int

Тип данных MPI_2REAL аналогичен тому, как если бы он был определен следующим образом (см. раздел 3.12).

MPI_TYPE_CONTIGOUS(2, MPI_REAL, MPI_2REAL)

Аналогичными выражениями задаются MPI_2INTEGER, MPI_2DOUBLE_PRECISION и MPI_2INT.

Тип данных MPI_FLOAT_INT аналогичен тому, как если бы он был объявлен следующей последовательностью инструкций.

type[0] = MPI_FLOAT
type[1] = MPI_INT
disp[0] = 0
disp[1] = sizeof(float)
block[0] = 1
block[1] = 1
MPI_TYPE_STRUCT(2, block, disp, type, MPI_FLOAT_INT)

Подобные выражения относятся и к MPI_LONG_INT и MPI_DOUBLE_INT.

Пример 4.17 Каждый процесс имеет массив 30 чисел типа double на языке Си. Для каждой из 30 областей надо вычислить значение и номер процесса, содержащего наибольшее значение.

... /* каждый процесс имет массив из 30 чисел двойной точности: ain[30] */ double ain[30], aout[30]; int ind[30]; struct { double val; int rank; } in[30], out[30]; int i, myrank, root; MPI_Comm_rank(MPI_COMM_WORLD, &myrank); for (i=0; i<30; ++i) { in[i].val = ain[i]; in[i].rank = myrank; } MPI_Reduce(in, out, 30, MPI_DOUBLE_INT, MPI_MAXLOC, root, comm); /* в этой точке результат помещается на корневой процесс */ if (myrank == root) { /* читаются выходные номера */ for (i=0; i<30; ++i) { aout[i] = out[i].val; ind[i] = out[i].rank; !номер обратно преобразуется в целое } }

Пример 4.18 Тот же пример для языка ФОРТРАН.

... ! каждый процесс имеет массив из 30 чисел двойной точности: ain(30) DOUBLE PRECISION ain(30), aout(30) INTEGER ind(30); DOUBLE PRECISION in(2,30), out(2,30) INTEGER i, myrank, root, ierr; MPI_COMM_RANK(MPI_COMM_WORLD, myrank); DO I=1, 30 in(1,i) = ain(i) in(2,i) = myrank ! myrank преобразуется к типу double END DO MPI_REDUCE(in, out, 30, MPI_2DOUBLE_PRECISION, MPI_MAXLOC, root, comm, ierr); ! в этой точке результат помещается на корневой процесс IF (myrank .EQ. root) THEN ! читаются выходные номера DO I= 1, 30 aout(i) = out(1,i) ind(i) = out(2,i) END DO END IF

Пример 4.19 Каждый процесс имеет непустой массив чисел. Требуется найти минимальное глобальное число, номер процесса, хранящего его, и его индекс в этом процессе.

#define LEN 1000 float val[LEN]; /* локальный массив значений */ int count; /* локальное количество значений */ int myrank, minrank, minindex; float minval; struct { float value; int index; } in, out; /* локальный minloc */ in.value = val[0]; in.index = 0; for (i=1; i < count; i++) if (in.value > val[i]) { in.value = val[i]; in.index = i; } /* глобальный minloc */ MPI_Comm_rank(MPI_COMM_WORLD, &myrank); in.index = myrank*LEN + in.index; MPI_Reduce(in, out, 1, MPI_FLOAT_INT, MPI_MINLOC, root, comm); /* в этой точке результат помещается на корневой процесс */ if (myrank == root) { minval = out.value; minrank = out.index / LEN; minindex = out.index % LEN; }

Объяснение: Данное здесь определение MPI_MINLOC и MPI_MAXLOC имеет то достоинство, что оно не приводит к необходимости какой-либо специальной обработки для этих двух операций: они обрабатываются, как и другие операции редукции. Если необходимо, программист может создать собственные определения MPI_MAXLOC и MPI_MINLOC . Недостаток определения состоит в том, что значения и индексы должны чередоваться, и индексы и переменные должны быть приведены к одному типу для языка ФОРТРАН.[]


next up previous contents
Next: Операции, определяемые пользователем Up: Глобальные операции редукции Previous: Предопределенные операции редукции   Contents
Alex Otwagin 2002-12-10