The OpenNET Project / Index page

[ новости /+++ | форум | wiki | теги | ]

Каталог документации / Раздел "Программирование, языки" / Оглавление документа
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



Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру