Проблема с использованием MPI_Sendrecv и MPI_Type_create_subarray для обмена 2D-гало - PullRequest
0 голосов
/ 02 ноября 2019

Я пытаюсь написать код MPI на C, чтобы проверить обмен гало / призраками между процессорами для двумерной матрицы / сетки, используя MPI_Sendrecv и MPI_Type_create_subarray. Я обнаружил, что мой код работает только для обмена данными в одном направлении (х-направлении, где данные находятся в смежной памяти), но не правильно обменивает его в другом направлении (у-направлении). Я думаю, что это, скорее всего, может быть связано с проблемой макета памяти, на которую ответили в предыдущих постах Джонатан-Дурси. Я предпочитаю использовать MPI_Type_create_subarray, который, кажется, также легче установить в трехмерной сетке. Может ли кто-нибудь помочь мне, как я могу обмениваться данными ореола?

Вот мой код:

#include "mpi.h"
#include <stdio.h>
#define BUFSIZE 2
#define HALO 1
int main(int argc, char *argv[])
{
  int i, j, rank, numprocs, buf[BUFSIZE+2*HALO][BUFSIZE+2*HALO];  
  int NDIM=2;
  MPI_Comm new_comm;
  MPI_Status status;
  MPI_Request request;

  MPI_Datatype xslice, yslice;
  FILE *file;

  int gsize[NDIM];
  gsize[0]=BUFSIZE+2*HALO;
  gsize[1]=BUFSIZE+2*HALO;

  MPI_Init(&argc, &argv);
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  MPI_Comm_size(MPI_COMM_WORLD, &numprocs);

  int nprocs[2]={2,2};
  int periods[2]={0,0};
  int procneigh[2][2];
  int coords[2];

  MPI_Cart_create(MPI_COMM_WORLD,NDIM,nprocs,periods,0,&new_comm);
  for (int i=0;i<NDIM;++i){
    MPI_Cart_shift(new_comm,i,1,&procneigh[i][0],&procneigh[i][1]);
  }
  MPI_Cart_coords(new_comm,rank,2,coords);

  int cnt=0;
  for (i=0; i<gsize[0]; i++){
    for(j=0; j<gsize[1]; j++){
      buf[i][j] = (rank+1) * 10+cnt;
      cnt++;;
    if(i<1||j<1||i>gsize[0]-2||j>gsize[1]-2) buf[i][j]=0;
      }
  }

  int TSIZE=gsize[0]*gsize[1];

  int sizes[NDIM];
  int subsizes[NDIM];
  int starts[NDIM];
  for(int i=0;i<NDIM;++i){
    sizes[i]=gsize[i];
    starts[i]=0;
  }

  subsizes[0]=1;
  subsizes[1]=BUFSIZE;
  MPI_Type_create_subarray(NDIM, sizes, subsizes, starts, MPI_ORDER_C, MPI_DOUBLE, &yslice);
  MPI_Type_commit(&yslice);


  subsizes[0]=BUFSIZE;
  subsizes[1]=1;
  MPI_Type_create_subarray(NDIM, sizes, subsizes, starts, MPI_ORDER_C, MPI_DOUBLE, &xslice);
  MPI_Type_commit(&xslice);
  int flag=1;

  MPI_Sendrecv(&buf[HALO][1], 1, yslice ,procneigh[0][0], flag, &buf[gsize[0]-1][1], 1, yslice, procneigh[0][1], flag, new_comm, &status);
  MPI_Sendrecv(&buf[gsize[0]-2][1], 1, yslice, procneigh[0][1], flag, &buf[HALO-1][1], 1, yslice, procneigh[0][0], flag, new_comm, &status);

  MPI_Sendrecv(&buf[1][HALO], 1, xslice, procneigh[1][0], flag, &buf[1][gsize[1]-1], 1, xslice, procneigh[1][1], flag, new_comm, &status);
  MPI_Sendrecv(&buf[1][gsize[1]-2], 1, xslice, procneigh[1][1], flag, &buf[1][HALO-1], 1, xslice, procneigh[1][0], flag, new_comm, &status); 

  int tmp;
  if (rank == 0) {
    for (int iproc = 0; iproc < numprocs; iproc++) {
      if (iproc) {
        MPI_Irecv(&buf[0][0],TSIZE,MPI_INT,iproc,0,MPI_COMM_WORLD,&request);
        MPI_Send(&tmp,0,MPI_INT,iproc,0,MPI_COMM_WORLD);
        MPI_Wait(&request,&status);
      }

      printf("---BEG----\n");
      for(i = 0; i < gsize[0]; i++) {
    for(j = 0; j < gsize[1]; j++) {
      printf("%d ",buf[i][j]);
          }
    printf("\n");
      }
      printf("---END----\n");
    }
  } else {
    MPI_Recv(&tmp,0,MPI_INT,0,0,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
    MPI_Rsend(&buf[0][0],TSIZE,MPI_INT,0,0,MPI_COMM_WORLD);
  }

  MPI_Finalize(); 
  return 0;
}

Вывод:

---BEG----
0 0 0 0 
0 15 16 25 
26 19 20 0 
0 35 36 45 
---END----
---BEG----
0 0 0 0 
16 25 26 0 
0 29 30 0 
36 45 46 0 
---END----
---BEG----
0 19 20 0 
0 35 36 45 
46 39 40 0 
0 0 0 0 
---END----
---BEG----
0 29 30 0 
36 45 46 0 
0 49 50 0 
0 0 0 0 
---END----

В то время как ожидаемый вывод долженбыть:

---BEG----
0 0 0 0 
0 15 16 25 
0 19 20 29 
0 35 36 45 
---END----
---BEG----
0 0 0 0 
16 25 26 0 
20 29 30 0 
36 45 46 0 
---END----
---BEG----
0 19 20 29 
0 35 36 45 
0 39 40 49 
0 0 0 0 
---END----
---BEG----
20 29 30 0 
36 45 46 0 
40 49 50 0 
0 0 0 0 
---END----
...