提问人:Amato.g 提问时间:11/14/2023 最后编辑:Amato.g 更新时间:11/14/2023 访问量:76
使用 MPI 对未按预期工作的矩阵进行逐列分解
Column-wise decomposition of a matrix not working as intended using MPI
问:
我有一个 NxM 矩阵,N=7 和 M=8,如下所示:
[0, 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]
它被编码到大小为 NxM 的一维数组中。
我想在 3 个进程之间执行按列分布,以便
进程 0 将具有:
[ 0, 1, 2,
8, 9, 10,
16, 17, 18,
24, 25, 26,
32, 33, 34,
40, 41, 42,
48, 49, 50]
进程 1 将具有:
[ 3, 4, 5,
11, 12, 13,
19, 20, 21,
27, 28, 29,
35, 36, 37,
43, 44, 45,
51, 52, 53]
进程 2 将具有:
[ 6, 7,
14, 15,
22, 23,
30, 31,
38, 39,
46, 47,
54, 55]
每个进程都以这种方式计算其局部 N 和 M 以及局部向量的长度:
int nloc = N;
int mloc = rank < M%nproc ? (M/nproc)+1 : M/nproc;
int *recv_vec = (int *)malloc(nloc*mloc*sizeof(int));
请注意,这是进程在它所属的通信器中的等级。(我有 3 个进程,所以分别是 0、1、2)。rank
为了执行我使用的分发,因为我必须向每个进程发送不同数量的列。
为了做到这一点,我创建了一个新的数据类型,以便可以将数字放在正确的位置并将其发送到正确的进程。MPI_Scatterv
MPI_Scatterv
MPI_Datatype col, col_type;
MPI_Type_vector(nloc, 1, M, MPI_INT, &col);
MPI_Type_commit(&col);
//I resized the newly created vector so that MPI_Scatterv knows the right offset for the subsequent elements
MPI_Type_create_resized(col, 0, sizeof(int), &col_type);
MPI_Type_commit(&col_type);
此时,可以完成数据的分发:
int sendcounts[]={3,3,2};
int displs[]={0,3,6};
MPI_Scatterv(matrix, sendcounts, displs, col_type, recv_vec, nloc*mloc, MPI_INT, 0, MPI_COMM_WORLD);
但实际情况是,由于我们发送了专栏
进程 0 接收此矩阵(显然在一维向量中)
[ 0, 8, 16, 24, 32, 40, 48,
1, 9, 17, 25, 33, 41, 49,
2, 10, 18, 26, 34, 42, 50]
等等其他过程。
所以我也创建了一个接收类型。MPI_Scatterv
MPI_Datatype recv_row, recv_row_type;
MPI_Type_vector(mloc,1,nloc,MPI_INT, &recv_row);
MPI_Type_commit(&recv_row);
MPI_Type_create_resized(recv_row, 0, sizeof(int), &recv_row_type);
MPI_Type_commit(&recv_row_type);
并以这种方式调用:MPI_Scatterv
MPI_Scatterv(matrix, sendcounts, displs, col_type, recv_vec, nloc, recv_row_type, 0, MPI_COMM_WORLD);
我期望收到的是我最初所说的,但收到的流程是这样的:
Process 0: 0 24 48 17 41 10 34 8 32 1 25 49 18 42 16 40 9 33 2 26 50
Process 1: 3 27 51 20 44 13 37 11 35 4 28 52 21 45 19 43 12 36 5 29 53
Process 2: 6 22 38 54 15 31 47 14 30 46 7 23 39 55
,有问题,但我不知道是什么。有人可以帮助我吗?recv_row_type
这是完整的代码:
#define N 7
#define M 8
int main(int argc, char *argv[]){
int matrix[N*M];
int menum, nproc, i, j;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &menum);
MPI_Comm_size(MPI_COMM_WORLD, &nproc);
//Matrix initialization
if (menum == 0) {
for (i = 0; i < N; i++) {
for (j = 0; j < M; j++) {
matrix[(i*M)+j] = i * M + j;
}
}
}
//Every process has its vector of size nloc*mloc
int nloc = N;
int mloc = menum < M%nproc ? (M/nproc)+1 : M/nproc;
int *recv_vec = (int *)malloc(nloc*mloc*sizeof(int));
//Create a custom datatype for a vector of nloc integers
MPI_Datatype col, col_type, recv_row, recv_row_type;
MPI_Type_vector(nloc, 1, M, MPI_INT, &col);
MPI_Type_commit(&col);
MPI_Type_create_resized(col, 0, sizeof(int), &col_type);
MPI_Type_commit(&col_type);
MPI_Type_vector(mloc,1,nloc,MPI_INT, &recv_row);
MPI_Type_commit(&recv_row);
MPI_Type_create_resized(recv_row, 0, sizeof(int), &recv_row_type);
MPI_Type_commit(&recv_row_type);
//Distributing data to other processes
int sendcounts[]={3,3,2};
int displs[]={0,3,6};
MPI_Scatterv(matrix, sendcounts, displs, col_type, recv_vec, nloc, recv_row_type, 0, MPI_COMM_WORLD);
//Printing data received by the process
printf("Il processo %d: ",menum);
for(i=0; i<nloc*mloc; i++){
printf("%d ",recv_vec[i]);
}
printf("\n");
//Freeing up memory and terminate MPI environment
free(recv_vec);
MPI_Type_free(&col);
MPI_Type_free(&col_type);
MPI_Type_free(&recv_row);
MPI_Type_free(&recv_row_type);
MPI_Finalize();
return 0;
}
答: 暂无答案
评论
MPI_Scatterv
nloc
mloc