2017-08-27 58 views
0

我正在处理MPI版本的BML自动机,但MPI_Scatter()将无法正常工作。我读here,对于集体通信功能,每个进程都需要它的数组副本,而不是初始化的分配空间。在我的代码中,有一个每个进程操作的子网格local_grid,以及一个只有root用户操作的起始大grid。我的意思是使用MPI数据类型的Scatter-Gather通信。我为每个网格和子网格分配空间,然后仅为根网格初始化网格。我错在哪里?变量的MPI散点图/聚集范围

 unsigned char*** local_grid; 
     unsigned char** grid; 

     MPI_Status stat; 
     MPI_Datatype rowtype; 

     MPI_Init(&argc, &argv); 
     MPI_Comm_rank(MPI_COMM_WORLD, &rank); 
     MPI_Comm_size(MPI_COMM_WORLD, &nproc); 
     local_n = N/nproc; 

     MPI_Type_contiguous(N + 2, /* count */ 
       MPI_UNSIGNED_CHAR, /* oldtype */ 
       &rowtype    /* newtype */ 
       ); 
     MPI_Type_commit(&rowtype); 

     /* Allocate space for 3D local grids*/ 
     local_grid = (unsigned char***)malloc(2 * sizeof(unsigned char**)); 
     for(i = 0; i < 2; i++) { 
      local_grid[i] = (unsigned char**)malloc((local_n + 2) * sizeof(unsigned char*)); 
      for(j = 0; j < local_n + 2; j++) { 
       local_grid[i][j] = (unsigned char*)malloc((N + 2) * sizeof(unsigned char)); 
      } 
     } 
     /* Initialize local grids*/ 
     for(i = 0; i < local_n + 2; i++) { 
      for(j = 0; j < N + 2; j++) { 
       local_grid[0][i][j] = 0; 
       local_grid[1][i][j] = 0; 
      } 
     } 
     /* Allocate 2D starting grid */ 
     grid = (unsigned char**)malloc(N * sizeof(unsigned char*)); 
     for(i = 0; i < N + 2; i++) { 
      grid[i] = (unsigned char*)malloc((N + 2) * sizeof(unsigned char)); 
     } 
     /* Root */ 
     if(rank == 0) { 
      /* initialize 2D starting grid */ 
      for(i = 0; i < N; i++) { 
       for(j = 0; j < N + 2; j++) { 
        grid[i][j] = (((float)rand())/RAND_MAX) > rho ? 0 : rand()%2 + 1; 
        grid[i][0] = grid[i][N+1] = 0; 
        printf("%2d ", grid[i][j]); 
       } 
       printf("\n"); 
      } 
     } 
     /* All */ 
     MPI_Scatter(grid[0], local_n, rowtype, local_grid[cur][1], local_n, rowtype, source, MPI_COMM_WORLD); 

     ... 

程序正确终止,但只有一个单一的行类型行从散点图()到根过程,没有任何其他的过程,尽管他们的人数通过。

回答

2

一个问题来自你声明/分配你的二维数组的方式。

你声明你的二维数组是指向数组的指针数组(例如矩阵行),但MPI需要一个连续的布局。

例如,您可以替换

grid = (unsigned char**)malloc(N * sizeof(unsigned char*)); 
for(i = 0; i < N; i++) { 
    grid[i] = (unsigned char*)malloc((N + 2) * sizeof(unsigned char)); 
} 

grid = (unsigned char**)malloc(N * sizeof(unsigned char*)); 
    grid[0] = (unsigned char*)malloc(N*(N+2)*sizeof(unsigned char)); 
    for(i = 1; i < N; i++) { 
     grid[i] = grid[i-1] + N + 2; 
    } 

,然后用grid[0]MPI_Scatter()MPI_Gather() buffer参数同样的事情必须适用于local_grid[0]local_grid[1]

当你需要释放网格时,你可以简单地

free(grid[0]); 
free(grid); 

注意到我不认为你的程序可以正常工作,如果N不是nproc

+0

多内循环,会发生什么?因此,如果您想在MPI_Gather/Scatter函数中传递子网格2D或3D,而无需知道参数,那么这是您要做的典型方法吗?我将在稍后修复N/nproc细节,我知道这一点。 – Caramelleamare

+0

对不起,我很难理解你的评论。 'grid'是一个指针数组。既然你在MPI中使用它,你需要确保'grid [1] [0]'正好在'grid [0] [N + 1]'旁边。我描述的方法完全是这样的:一次分配完整的数组,然后构建指针数组,使它们都指向完整的数组。顺便说一句,我刚刚注意到你的分配错误,我重复了它:它应该是'for(i = 0; i

+0

好吧,所以对于3D数组'grid [1] [0] [0 ]'应该在'grid [0] [N + 1] [N + 1]'旁边?我无法弄清楚如何编写它,我想用一个嵌套循环(?)来想象。 – Caramelleamare