如何获得块循环分布?

时间:2015-01-24 18:09:14

标签: c matrix io block mpi

我试图以块循环方式分发我的矩阵。我从这个问题中学到了很多东西(MPI IO Reading and Writing Block Cyclic Matrix),但这不是我真正需要的。

让我解释一下我的问题。

假设我有这个尺寸为12 x 12的矩阵,我希望在尺寸为2 x 3的处理器网格上分布,这样第一个处理器就会得到粗体元素:

A =

    1     2     3     4     5     6     7     8     9    10    11    12
    13    14    15    16    17    18    19    20    21    22    23    24
    25    26    27    28    29    30    31    32    33    34    35    36
    37    38    39    40    41    42    43    44    45    46    47    48
    49    50    51    52    53    54    55    56    57    58    59    60
    61    62    63    64    65    66    67    68    69    70    71    72
    73    74    75    76    77    78    79    80    81    82    83    84
    85    86    87    88    89    90    91    92    93    94    95    96
    97    98    99   100   101   102   103   104   105   106   107   108
   109   110   111   112   113   114   115   116  117   118   119   120
   121   122   123   124   125   126   127   128   129   130   131   132
   133   134   135   136   137   138   139   140   141   142   143   144

所以,基本上,我想用尺寸为2 x 2的块对矩阵进行分区,然后以这种方式将这些块分配给处理器(编号从1到6):

1 2 3 1 2 3
4 5 6 4 5 6
1 2 3 1 2 3
4 5 6 4 5 6

我试图在上面的链接问题中实现它,但问题是我的第一个处理器的本地数组是按列形式形成的,即它看起来像这样

1, 13, 49, 61, 97, 109, 2, 14, 50, 62, 98, 110, 7, 19, 55, 67, 103, 115, 8, 20, 56, 68, 104, 116

这是我的C代码:


    #include    "stdio.h"
    #include    "string.h"
    #include    "stdlib.h"
    #include    "mpi.h"

    #define     N           12
    #define     P           2
    #define     Q           3

    int main(int argc, char **argv) {
        int rank;
        int size;

        double *A;
        int A_size;

        MPI_Datatype filetype;
        MPI_File fin;

        MPI_Status status;

        MPI_Init(&argc, &argv);

        MPI_Comm_rank(MPI_COMM_WORLD, &rank);
        MPI_Comm_size(MPI_COMM_WORLD, &size);

        /**
         * Reading from file.
         */
        int gsizes[2], distribs[2], dargs[2], psizes[2];

        gsizes[0] = N; /* no. of rows in global array */
        gsizes[1] = N; /* no. of columns in global array*/

        distribs[0] = MPI_DISTRIBUTE_CYCLIC;
        distribs[1] = MPI_DISTRIBUTE_CYCLIC;

        dargs[0] = 2; // no of rows in block
        dargs[1] = 2; // no of cols in block

        psizes[0] = P; /* no. of processes in vertical dimension
         of process grid */
        psizes[1] = Q; /* no. of processes in horizontal dimension
         of process grid */

        MPI_Type_create_darray(P * Q, rank, 2, gsizes, distribs, dargs, psizes,
                MPI_ORDER_FORTRAN, MPI_DOUBLE, &filetype);
        MPI_Type_commit(&filetype);

        MPI_File_open(MPI_COMM_WORLD, "A.txt",
                MPI_MODE_RDONLY,
                MPI_INFO_NULL, &fin);

        MPI_File_set_view(fin, 0, MPI_DOUBLE, filetype, "native",
                MPI_INFO_NULL);

        A_size = (N * N) / (P * Q);
        A = (double*) malloc(A_size * sizeof(double));
        MPI_File_read_all(fin, A, A_size,
                MPI_DOUBLE, &status);

        MPI_File_close(&fin);

        printf("\n======\ni = %d\n", rank);
        printf("A : ");
        for (int i = 0; i < A_size; i++) {
            printf("%lg ", A[i]);
        }

        MPI_Finalize();
        return 0;
    }

我真正想要的是那些2 x 2块是连续写入的,即第一个处理器的本地阵列看起来像这样;

1, 13, 2, 14, 49, 61, 50, 62, 97, 109, 98, 110, ... 

我假设我需要定义另一个MPI_Datatype(如vector或subarray),但我无法弄明白我将如何实现它。

提前致谢!

Edit

我想我已经部​​分解决了我的问题。基本上,每个处理器最终将以FORTRAN顺序的4 x 6矩阵结束,然后使用MPI_Create_subarray(...)我可以轻松地提取2 x 2块。

但我希望每个处理器将其块行发送到同一列中的每个处理器,反之亦然。处理器在网格中编号

1 2 3
4 5 6

因此,例如,在第一步中,处理器1应该发送他的块行

1  2  7  8
13 14 19 20

到处理器4;和他的块栏

1   2
13  14
49  50
61  62
97  98
109 110

到处理器2和3。

我创建了笛卡尔传播者,并使用MPI_Cart_sub()来创建行式和列式通信器。

我想我应该使用MPI_Bcast(),但是我不知道如何将MPI_Bcast()与MPI_Type_create_subarray()结合起来。我应该先将提取的子数组复制到某个local_array,然后再复制到Bcast(local_array)。但是,MPI_Type_create_subarray()只给我&#34;查看&#34;在子阵列上,实际上并非如此,所以我想出的最佳解决方案是Isend-Irecv root-&gt; root。

有更优雅的解决方案吗?

0 个答案:

没有答案