2017-08-27 218 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