如何使用MPI_Scatterv将矩阵行发送到所有进程?

我正在使用MPI接口。 我想分割矩阵(按行)并在每个过程中分配部分。

例如,我有这个7×7方阵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个进程,因此拆分可能是:

  • 进程0获取行0,1
  • 进程1获取第2,3,4行
  • 进程2获取行5,6

在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  #include  #include  #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(); } 

当我尝试读取分散的数据时,我收到了分段错误,表明分散操作不起作用。 我已经用一维数组做了这个并且它工作了。 但是对于二维数组,事情变得有点棘手。

你能帮我找一下这个虫子吗?

谢谢

MPI_Scatterv需要一个指向数据的指针,数据应该在内存中连续。 您的程序在第二部分很好,但MPI_Scatterv接收指向数据指针的指针。 因此改变它是一件好事:

 MPI_Scatterv(&m[0][0], sendcounts, displs, MPI_DOUBLE, &mParts[0][0], sendcounts[myrank], MPI_DOUBLE, root, MPI_COMM_WORLD); 

对于sendcountsdisplssendcounts一些要改变的事情:要去2D,这些计数应该乘以n 。 并且MPI_Scatterv的接收计数不再是rows ,而是sendcouts[myrank]

这是最终的代码:

 #include  #include  #include  #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 

如果您想了解有关2Darrays和MPI的更多信息,请查看此处

另请参阅PETSc库的DMDA结构