我有一个 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
) 中,如下所示: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];
}
}
}
现在,我有兴趣将
Foo2D
发送到排名 1,并将其放置在 Foo3D
中的位置。事实上,我知道我可以将 Foo2D
发送到排名 1 为:if (myrank == 0)
{
MPI_Send(Foo2D,sizeof_Foo2D,MPI_INT,1,100,MPI_COMM_WORLD);
}
else if (myrank == 1)
{
MPI_Recv(Foo2D,sizeof_Foo2D,MPI_INT,0,100,MPI_COMM_WORLD, &status);
}
然后将接收到的排名 1 的
Foo2D
分配到它在 Foo3D
中的位置,如下所示:if (myrank == 1)
{
for (int j = 0; j < ny; j++) {
for (int k = 0; k < nz; k++) {
Foo3D[0][j][k] = Foo2D[j][k];
}
}
}
不使用这个过程和
Foo2D
作为中间变量,是否可以将排名 0 中的 Foo3D
切片直接发送到 到它在排名 1 中的等效位置?事实上,我不想将整个 Foo3D
发送到 1 级,因为它是一个非常大的数组,我有兴趣只将它的一部分发送到 1 级。 最佳答案
您将数组 Foo3D
定义为 int[nx][ny][nz]
。因为C/C++是row-major语言,所以用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);
}
另一方面 ,如果您想使用缓冲区( Zero-Copy )发送 非连续 数据 而没有 ,您可以创建一个自定义 MPI 数据类型来表示要复制的数据,并直接从源发送缓冲区,并且 MPI 将读取您指定的数据,即使它在内存中是不连续的。这可以使用
MPI_Type_vector
来完成。例如,如果要发送值 where
k=0
,即网格面Foo[i][j][0]
。首先,创建表示要发送的网格面的数据类型。
// 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);
}
关于c++ - 如何使用 MPI 发送 3D 数组的切片?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57564875/