我试图用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----