我正在使用MPI界面。我想分割矩阵(按行)并在每个过程中分配部分。
例如,我有这个7x7方阵M。
M = [
0.00 1.00 2.00 3.00 4.00 5.00 6.00
7.00 8.00 9.00 10.00 11.00 12.00 13.00
14.00 15.00 16.00 17.00 18.00 19.00 20.00
21.00 22.00 23.00 24.00 25.00 26.00 27.00
28.00 29.00 30.00 31.00 32.00 33.00 34.00
35.00 36.00 37.00 38.00 39.00 40.00 41.00
42.00 43.00 44.00 45.00 46.00 47.00 48.00
];
我有3个进程,因此拆分可能是:
在Scatterv之后,它应该如下所示:
Process 0:
M0 = [
0.00 1.00 2.00 3.00 4.00 5.00 6.00
7.00 8.00 9.00 10.00 11.00 12.00 13.00
];
Process 1:
M1 = [
14.00 15.00 16.00 17.00 18.00 19.00 20.00
21.00 22.00 23.00 24.00 25.00 26.00 27.00
28.00 29.00 30.00 31.00 32.00 33.00 34.00
];
Process 2:
M2 = [
35.00 36.00 37.00 38.00 39.00 40.00 41.00
42.00 43.00 44.00 45.00 46.00 47.00 48.00
];
我认为我对自己想要实现的目标非常清楚。随意问我是否解释不好。
现在,我告诉你我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#define BLOCK_LOW(id,p,n) ((id)*(n)/(p))
#define BLOCK_HIGH(id,p,n) ((id+1)*(n)/(p) - 1)
#define BLOCK_SIZE(id,p,n) ((id+1)*(n)/(p) - (id)*(n)/(p))
#define BLOCK_OWNER(index,p,n) (((p)*((index)+1)-1)/(n))
void **matrix_create(size_t m, size_t n, size_t size) {
size_t i;
void **p= (void **) malloc(m*n*size+ m*sizeof(void *));
char *c= (char*) (p+m);
for(i=0; i<m; ++i)
p[i]= (void *) c+i*n*size;
return p;
}
void matrix_print(double **M, size_t m, size_t n, char *name) {
size_t i,j;
printf("%s=[",name);
for(i=0; i<m; ++i) {
printf("\n ");
for(j=0; j<n; ++j)
printf("%f ",M[i][j]);
}
printf("\n];\n");
}
main(int argc, char *argv[]) {
int npes, myrank, root = 0, n = 7, rows, i, j, *sendcounts, *displs;
double **m, **mParts;
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD,&npes);
MPI_Comm_rank(MPI_COMM_WORLD,&myrank);
// Matrix M is generated in the root process (process 0)
if (myrank == root) {
m = (double**)matrix_create(n, n, sizeof(double));
for (i = 0; i < n; ++i)
for (j = 0; j < n; ++j)
m[i][j] = (double)(n * i + j);
}
// Array containing the numbers of rows for each process
sendcounts = malloc(n * sizeof(int));
// Array containing the displacement for each data chunk
displs = malloc(n * sizeof(int));
// For each process ...
for (j = 0; j < npes; j++) {
// Sets each number of rows
sendcounts[j] = BLOCK_SIZE(j, npes, n);
// Sets each displacement
displs[j] = BLOCK_LOW(j, npes, n);
}
// Each process gets the number of rows that he is going to get
rows = sendcounts[myrank];
// Creates the empty matrixes for the parts of M
mParts = (double**)matrix_create(rows, n, sizeof(double));
// Scatters the matrix parts through all the processes
MPI_Scatterv(m, sendcounts, displs, MPI_DOUBLE, mParts, rows, MPI_DOUBLE, root, MPI_COMM_WORLD);
// This is where I get the Segmentation Fault
if (myrank == 1) matrix_print(mParts, rows, n, "mParts");
MPI_Finalize();
}
当我尝试读取分散的数据时,我收到了分段错误,表明分散操作不起作用。我已经使用一维数组做到了这一点并且有效。但是对于二维数组,事情变得有点棘手。
你能帮我找到这个错误吗?
由于
答案 0 :(得分:2)
MPI_Scatterv
需要指向数据的指针,数据应该在内存中连续。你的程序在第二部分没问题,但MPI_Scatterv
收到指向数据指针的指针。因此改变它是一件好事:
MPI_Scatterv(&m[0][0], sendcounts, displs, MPI_DOUBLE, &mParts[0][0], sendcounts[myrank], MPI_DOUBLE, root, MPI_COMM_WORLD);
sendcounts
和displs
还有一些要改变的地方:要转到2D,这些计数应乘以n
。 MPI_Scatterv
中的接收次数不再是rows
,而是sendcouts[myrank]
。
以下是最终代码:
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#define BLOCK_LOW(id,p,n) ((id)*(n)/(p))
#define BLOCK_HIGH(id,p,n) ((id+1)*(n)/(p) - 1)
#define BLOCK_SIZE(id,p,n) ((id+1)*(n)/(p) - (id)*(n)/(p))
#define BLOCK_OWNER(index,p,n) (((p)*((index)+1)-1)/(n))
void **matrix_create(size_t m, size_t n, size_t size) {
size_t i;
void **p= (void **) malloc(m*n*size+ m*sizeof(void *));
char *c= (char*) (p+m);
for(i=0; i<m; ++i)
p[i]= (void *) c+i*n*size;
return p;
}
void matrix_print(double **M, size_t m, size_t n, char *name) {
size_t i,j;
printf("%s=[",name);
for(i=0; i<m; ++i) {
printf("\n ");
for(j=0; j<n; ++j)
printf("%f ",M[i][j]);
}
printf("\n];\n");
}
main(int argc, char *argv[]) {
int npes, myrank, root = 0, n = 7, rows, i, j, *sendcounts, *displs;
double **m, **mParts;
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD,&npes);
MPI_Comm_rank(MPI_COMM_WORLD,&myrank);
// Matrix M is generated in the root process (process 0)
if (myrank == root) {
m = (double**)matrix_create(n, n, sizeof(double));
for (i = 0; i < n; ++i)
for (j = 0; j < n; ++j)
m[i][j] = (double)(n * i + j);
}
// Array containing the numbers of rows for each process
sendcounts = malloc(n * sizeof(int));
// Array containing the displacement for each data chunk
displs = malloc(n * sizeof(int));
// For each process ...
for (j = 0; j < npes; j++) {
// Sets each number of rows
sendcounts[j] = BLOCK_SIZE(j, npes, n)*n;
// Sets each displacement
displs[j] = BLOCK_LOW(j, npes, n)*n;
}
// Each process gets the number of rows that he is going to get
rows = sendcounts[myrank]/n;
// Creates the empty matrixes for the parts of M
mParts = (double**)matrix_create(rows, n, sizeof(double));
// Scatters the matrix parts through all the processes
MPI_Scatterv(&m[0][0], sendcounts, displs, MPI_DOUBLE, &mParts[0][0], sendcounts[myrank], MPI_DOUBLE, root, MPI_COMM_WORLD);
// This is where I get the Segmentation Fault
if (myrank == 1) matrix_print(mParts, rows, n, "mParts");
MPI_Finalize();
}
如果您想了解有关2D数组和MPI的更多信息,请查看here