Пример использования MPI_Type_create_subarray для циклического распределения 2d - PullRequest
1 голос
/ 27 июня 2019

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

Я знаю, что MPI_Type_create_darray даст мне двумерное циклическое распределение, но оно не совместимо с SCALAPACK технологической сеткой.

Я бы сделал циклическое распределение 2d блоков, используя MPI_Type_create_subarray и передал бы матрицы в подпрограммы SCALAPACK.

Могу ли я привести пример, показывающий это?

1 Ответ

1 голос
/ 27 июня 2019

На ваш вопрос есть как минимум две части.В следующих разделах рассматриваются эти две составляющие части, но мы оставляем вам интеграцию этих двух компонентов.Пример кода, приведенный ниже в обоих разделах, наряду с пояснениями, приведенными в ссылке ScaLapack ниже, должен дать некоторые рекомендации ...

С DeinoMPI :

Следующий пример кода иллюстрирует MPI_Type_create_subarray.

#include "mpi.h"
#include <stdio.h>

int main(int argc, char *argv[])
{
    int myrank;
    MPI_Status status;
    MPI_Datatype subarray;
    int array[9] = { -1, 1, 2, 3, -2, -3, -4, -5, -6 };
    int array_size[] = {9};
    int array_subsize[] = {3};
    int array_start[] = {1};
    int i;

    MPI_Init(&argc, &argv);

    /* Create a subarray datatype */
    MPI_Type_create_subarray(1, array_size, array_subsize, array_start, MPI_ORDER_C, MPI_INT, &subarray);
    MPI_Type_commit(&subarray);

    MPI_Comm_rank(MPI_COMM_WORLD, &myrank);

    if (myrank == 0)
    {
        MPI_Send(array, 1, subarray, 1, 123, MPI_COMM_WORLD);
    }
    else if (myrank == 1)
    {
        for (i=0; i<9; i++)
            array[i] = 0;
        MPI_Recv(array, 1, subarray, 0, 123, MPI_COMM_WORLD, &status);
        for (i=0; i<9; i++)
            printf("array[%d] = %d\n", i, array[i]);
        fflush(stdout);
    }

    MPI_Finalize();
    return 0;
}

И из ScaLapack в C основы :

К сожалению, нет интерфейса C для ScaLAPACK или PBLAS. Все параметры должны передаваться в подпрограммы и функции по ссылке, вы также можете определить константы (i_one для 1, i_negone для -1, d_two для 2.0E + 0 и т. Д.) Для передачив рутины. Матрицы должны иметь 1d массив (A [i + lda * j], а не A [i] [j])

Для вызова подпрограмм ScaLAPACK в вашей программе вы должны сначала инициализировать грид через подпрограммы BLACS (BLACS достаточно).Во-вторых, вы должны распределить свою матрицу по сетке процессов (блок циклического 2d-распределения).Вы можете сделать это с помощью процедуры pdgeadd_ PBLAS.Эта процедура рассчитывает сумму двух матриц A, B: B: = альфа A + бета B).Матрицы могут иметь различное распределение, в частности матрица A может принадлежать только одному процессу, поэтому, установив alpha = 1, beta = 0, вы можете просто скопировать вашу нераспределенную матрицу A в распределенную матрицу B.

В-третьих, вызвать pdgeqrf_для матрицы B. В конце части кода ScaLAPACK вы можете собирать результаты по одному процессу (просто скопируйте распределенную матрицу в локальную через pdgeadd_).Наконец, закройте сетку с помощью blacs_gridexit_ и blacs_exit _.

В конце концов, программа, использующая ScaLAPACK, должна содержать следующее:

void main(){
// Useful constants
const int i_one = 1, i_negone = -1, i_zero = 0;
const double zero=0.0E+0, one=1.0E+0;

... (See the rest of code in linked location above...)
...