使用MPI_Sendrecv和MPI_Type_create_子阵列进行二维光晕交换时出现问题

使用MPI_Sendrecv和MPI_Type_create_子阵列进行二维光晕交换时出现问题,c,mpi,C,Mpi,我试图用C语言编写MPI代码,使用MPI_Sendrecv和MPI_Type_create_子数组测试2D矩阵/网格中处理器之间的halo/ghost交换。我发现me代码只能在一个方向(x方向,数据在内存中是连续的)上交换数据,但不能在另一个方向(y方向)上正确地交换数据。我认为这很可能是因为jonathan dursi在之前的文章中回答了内存布局问题。我更喜欢使用MPI_Type_create_子数组,它看起来也更容易在三维网格中设置。有人能帮我交换halo数据吗 这是我的密码: #inclu

我试图用C语言编写MPI代码,使用MPI_Sendrecv和MPI_Type_create_子数组测试2D矩阵/网格中处理器之间的halo/ghost交换。我发现me代码只能在一个方向(x方向,数据在内存中是连续的)上交换数据,但不能在另一个方向(y方向)上正确地交换数据。我认为这很可能是因为jonathan dursi在之前的文章中回答了内存布局问题。我更喜欢使用MPI_Type_create_子数组,它看起来也更容易在三维网格中设置。有人能帮我交换halo数据吗

这是我的密码:

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

您确定您的缓冲区位于索引1而不是0吗?感谢Giles的关注。我确实检查了使用0索引运行,但这并不能解决问题。事实上。。。您所要做的就是使用
MPI\u INT
而不是
MPI\u DOUBLE
创建子阵列,谢谢。这是个好建议。我将MPI_DOUBLE更改为MPI_INT。但它仍然不能解决问题。仅供参考,当我使用MPI_Type_vector时,代码按预期工作。我使用Open MPI 4.0.2获得了您期望的输出。您正在运行哪个库(供应商和版本)?
---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----