| |
Оператор MPI_MINLOC используется для расчета глобального минимума и соответствующего ему индекса. MPI_MAXLOC аналогично считает глобальный максимум и индекс. Одно из применений этих операций - вычисление глобального минимума (максимума) и номера процесса, содержащего это значение.
Операция, которая определяет MPI_MAXLOC , такова:
где w = max(u, v) и
MPI_MINLOC определен аналогично:
где w = min(u, v) и
Обе операции ассоциативны и коммутативны. Отметим, что если MPI_MAXLOC применяется для последовательности пар (u, 0), (u, 1), ..., (u, n-1), то возвращаемое значение есть (u, r), где u=max(u и 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 . Недостаток определения состоит в том, что значения и индексы должны чередоваться, и индексы и переменные должны быть приведены к одному типу для языка ФОРТРАН.[]
Закладки на сайте Проследить за страницей |
Created 1996-2024 by Maxim Chirkov Добавить, Поддержать, Вебмастеру |