使用MPI_Sendrecv和MPI_Type_create_subarray进行二维光晕交换时发生的问题

时间:2019-11-02 13:17:27

标签: c mpi

我试图用C编写MPI代码,以使用MPI_Sendrecv和MPI_Type_create_subarray测试跨处理器的2D矩阵/网格的光晕/重影交换。我发现我的代码仅适用于在一个方向(x方向,其中数据在内存中是连续的)上交换数据,但不能在另一个方向(y方向)上正确交换数据。我认为这很可能是由于jonathan-dursi在先前的文章中回答的内存布局问题。我更喜欢使用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----

0 个答案:

没有答案