C++ 如何使用MPI发送3D阵列的切片?

C++ 如何使用MPI发送3D阵列的切片?,c++,mpi,C++,Mpi,我有一个3D数组Foo3D(50 x 100 x 100),排列在0和1之间Foo3D的分配方式如下: int nx = 50; int ny = 100; int nz = 100; typedef int nRarray[100][50]; nRarray *Foo3D; if ((Foo3D = (nRarray *)malloc((nx*ny*nz)*sizeof(int))) == 0) {fprintf(stderr,"malloc1 Fail \n"); return 1;} 我

我有一个3D数组
Foo3D
(50 x 100 x 100),排列在0和1之间
Foo3D
的分配方式如下:

int nx = 50;
int ny = 100;
int nz = 100;
typedef int nRarray[100][50];
nRarray *Foo3D;
if ((Foo3D = (nRarray *)malloc((nx*ny*nz)*sizeof(int))) == 0) {fprintf(stderr,"malloc1 Fail \n"); return 1;}
我将一些数字分配给0级的
Foo3D
,并将其保存到一个新的二维数组(
Foo2D
)中,如下所示:

然后将排名1中接收到的
Foo2D
分配到其在
Foo3D
中的位置,如下所示:

if (myrank == 0) {
for (int j = 0; j < ny; j++) {
 for (int k = 0; k < nz; k++) {

   Foo3D[0][j][k] = j + k;
   Foo2D[j][k] = Foo3D[0][j][k];
}
 } 
}
if (myrank == 1)
{
for (int j = 0; j < ny; j++) {
 for (int k = 0; k < nz; k++) {

   Foo3D[0][j][k] = Foo2D[j][k];
}
 } 
}
if(myrank==1)
{
对于(int j=0;j

不使用此过程和
Foo2D
作为中间变量,是否可以将秩0中的
Foo3D
切片直接发送到秩1中的等效位置?事实上,我不想将整个
Foo3D
发送到排名1,因为它是一个非常大的数组,我只想将其中的一部分发送到排名1。

您将数组
Foo3D
定义为
int[nx][ny][nz]
。因为C/C++是行主语言,所以表示为
Foo3D[0][j][k]
的网格面元素在内存中实际上是连续的

因此,您只需使用以下命令将面发送到
i=0

if (myrank == 0) {
    MPI_Send(Foo3D, ny*nz, MPI_INT, 1, 100, MPI_COMM_WORLD);
}
else if (myrank == 1){
    MPI_Recv(Foo3D, ny*nz, MPI_INT, 0, 100, MPI_COMM_WORLD, &status);
}
另一方面,如果要在不使用缓冲区()的情况下发送非连续的数据,则可以创建表示要复制的数据的自定义MPI数据类型,并直接从源缓冲区发送,MPI将读取您指定的数据,即使该数据在内存中是非连续的。这可以通过使用

例如,如果要将值发送到
k=0
,即网格面
Foo[i][j][0]

首先,创建一个表示要发送的网格面的数据类型

然后,您可以使用以下方式发送和接收:

if (myrank == 0) {
    MPI_Send(Foo3D, 1, cubeface, 1, cubefacesize, MPI_COMM_WORLD);
} else if (myrank == 1) {
    MPI_Recv(Foo3D, 1, cubeface, 0, cubefacesize, MPI_COMM_WORLD, &status);
}

必须在连续内存中分配数组,但代码段不显示它们是如何声明的。如果您需要更多帮助,请上传。@GillesGouaillardet已完成。某些内容仍然缺少,这还不是一个完整的文档。如果(…)
测试中,
else也可能有输入错误。您的派生数据类型在Fortran中是正确的,但这里是C。@GillesGouaillardet您是指行数组和主列数组吗?因为在FORTRAN中数组是列主数组,而在C中数组是行主数组,对吗?@GillesGouaillardet你说得对!非常感谢。我会更新我的答案。@AloneProgrammer是的,我相信这就是Gilles的意思。我已经相应地更新了答案。让我们来看看。
// Create a data type and save its size
MPI_Datatype cubeface;
int cubefacesize;
MPI_Type_vector(nx*ny, 1, nz, MPI_INT, &cubeface);
MPI_Type_commit(&cubeface);
MPI_Type_size(cubeface, &cubefacesize);
if (myrank == 0) {
    MPI_Send(Foo3D, 1, cubeface, 1, cubefacesize, MPI_COMM_WORLD);
} else if (myrank == 1) {
    MPI_Recv(Foo3D, 1, cubeface, 0, cubefacesize, MPI_COMM_WORLD, &status);
}