我试图以块循环方式分发我的矩阵。我从这个问题中学到了很多东西(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。
有更优雅的解决方案吗?