使用MPI_Type_create_subarray进行2d循环分布的示例

时间:2019-06-27 11:08:23

标签: c linear-algebra lapacke mpi-io scalapack

我想举一个例子,说明如何使用MPI_Type_create_subarray为大型矩阵建立2D循环分布。

我知道MPI_Type_create_darray会给我2D循环分布,但它与SCALAPACK流程网格不兼容。

我将使用MPI_Type_create_subarray进行2d块循环分布,并将矩阵传递给SCALAPACK例程。

我可以举个例子显示这个吗?

1 个答案:

答案 0 :(得分:1)

您的问题至少有两个部分。以下各节讨论了这两个组成部分,但您将两者保持集成。以下两节中包含的示例代码以及下面的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 in C essentials

  

不幸的是,ScaLAPACK或PBLAS没有C接口。   参数应通过引用传递到例程和函数中,   您还可以定义常量(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:= alpha A + beta B)。   矩阵可以具有不同的分布,特别是矩阵A可以是   仅由一个进程拥有,因此,可以简单地将alpha = 1,beta = 0设置为   将您的非分布式矩阵A复制到分布式矩阵B中。

     

第三,为矩阵B调用pdgeqrf_。在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...)