使用MPI_Gather在c++中3d数组
Using MPI_Gather for 3d array in c++?
我正在尝试并行化for
循环操作,该操作夹在两个for
循环之间。
在每个处理器中计算完数据(3d数组)后,我想将每个处理器的数据收集回根节点以进行进一步处理。我尝试使用MPI_Gather
函数将数据返回到根节点。使用此函数,从根处理器收集回数据,但不从其他处理器收集数据。
int main(int argc, char * argv[]) {
int i,k,l,j;
int Np = 7, Nz = 7, Nr = 4;
int mynode, totalnodes;
MPI_Status status;
long double ***k_p, ***k_p1;
int startvalp,endvalp;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD, &totalnodes);
MPI_Comm_rank(MPI_COMM_WORLD, &mynode);
// Allocation of memory
Allocate_3D_R(k_p,(Nz+1),(Np+1),(Nr+1));
Allocate_3D_R(k_p1,(Nz+1),(Np+1),(Nr+1));
// startvalp represents the local starting value for each processor
// endvalp represents the local ending value for each processor
startvalp = (Np+1)*mynode/totalnodes - 0;
endvalp = startvalp + (((Np+1)/totalnodes) -1);
for(l = 0 ; l <= 1 ; l++){
for(k=startvalp; k<=endvalp; k++){
// for loop parallelized between the processors
// original loop: for(k=0; k<= Np; k++)
for(i=0; i<=1; i++){
k_p[i][k][l] = l+k+i;
}
}
}
// For Np = 7 and for two processors ;
// k = 0 - 3 is calculated in processor 0;
// k = 4 - 7 is calculated in processor 1;
// Now I need to collect the value of k_p from processor 1
// back to the root processor.
// MPI_Gather function is used.
for(l = 0 ; l <= 1 ; l++){
for(k=startvalp; k<=endvalp; k++){
for(i=0; i<=1; i++){
MPI_Gather(&(k_p[i][k][l]),1, MPI_LONG_DOUBLE,&(k_p1[i][k][l]),1, MPI_LONG_DOUBLE, 0, MPI_COMM_WORLD);
}
}
}
// Using this the k_p is collected from root processor and stored
// in the k_p1 variable, but from the slave processor it is not
// collected back to the root processor.
if(mynode == 0){
for(l = 0 ; l <= 1 ; l++){
for(k=0; k<=Np; k++){
for(i=0i<=1;i++){
cout << "Processor "<<mynode;
cout << ": k_p["<<i<<"]["<<k<<"]["<<l<<"] = " <<k_p1[i][k][l]<<endl;
}
}
}
}
MPI_Finalize();
} // end of main
void Allocate_3D_R(long double***& m, int d1, int d2, int d3) {
m=new long double** [d1];
for (int i=0; i<d1; ++i) {
m[i]=new long double* [d2];
for (int j=0; j<d2; ++j) {
m[i][j]=new long double [d3];
for (int k=0; k<d3; ++k) {
m[i][j][k]=0.0;
}
}
}
}
输出如下:
Processor 0: k_p[0][0][0] = 0
Processor 0: k_p[1][0][0] = 1
Processor 0: k_p[0][1][0] = 1
Processor 0: k_p[1][1][0] = 2
Processor 0: k_p[0][2][0] = 2
Processor 0: k_p[1][2][0] = 3
Processor 0: k_p[0][3][0] = 3
Processor 0: k_p[1][3][0] = 4
Processor 0: k_p[0][4][0] = 0
Processor 0: k_p[1][4][0] = 0
Processor 0: k_p[0][5][0] = 0
Processor 0: k_p[1][5][0] = 0
Processor 0: k_p[0][6][0] = 0
Processor 0: k_p[1][6][0] = 0
Processor 0: k_p[0][7][0] = 0
Processor 0: k_p[1][7][0] = 0
Processor 0: k_p[0][0][1] = 1
Processor 0: k_p[1][0][1] = 2
Processor 0: k_p[0][1][1] = 2
Processor 0: k_p[1][1][1] = 3
Processor 0: k_p[0][2][1] = 3
Processor 0: k_p[1][2][1] = 4
Processor 0: k_p[0][3][1] = 4
Processor 0: k_p[1][3][1] = 5
Processor 0: k_p[0][4][1] = 0
Processor 0: k_p[1][4][1] = 0
Processor 0: k_p[0][5][1] = 0
Processor 0: k_p[1][5][1] = 0
Processor 0: k_p[0][6][1] = 0
Processor 0: k_p[1][6][1] = 0
Processor 0: k_p[0][7][1] = 0
Processor 0: k_p[1][7][1] = 0
根处理器的数据被传输,但不从其他处理器传输。我尝试使用MPI_Send
和MPI_Recv
函数,没有遇到上述问题,但对于for
循环的大值,它需要更多的时间。
因此,有人能提供解决上述问题的方法吗?
这里的问题实际上与2d中的问题相似:MPI_Type_create_subarray和MPI_Gather;这里有一个很长的答案,涵盖了大部分的关键点。
收集多维数组部分比只收集一维数组更棘手,因为你收集的数据实际上是重叠的。例如,排名1的第一行位于排名0的第一行和第二行之间。所以你需要(a)使用mpi_gatherv
,这样你就可以指定位移,(b)显式地设置数据类型的范围,以促进重叠。
理解复杂数据结构的发送和接收(在MPI中,或在其他任何地方)都是关于理解内存中数据的布局——这对于从代码中获得高性能至关重要。
说到内存的布局,你的Allocate3d不会在这里工作;问题是它分配的内存可能不是连续的。如果以这种方式分配一个10x10x10数组,并不能保证元素[1][0][0]紧跟在元素[0][9][9]之后。这是C/c++中的一个常见问题,它没有任何内置的多维数组概念。您需要这样做:
void Allocate_3D_R(long double***& m, int d1, int d2, int d3) {
m=new long double** [d1];
for (int i=0; i<d1; ++i) {
m[i]=new long double* [d2];
}
m[0][0] = new long double[d1*d2*d3];
for (int i=0; i<d1; ++i) {
for (int j=0; j<d2; ++j) {
if (i!=0 && j!=0)
m[i][j]=&(m[0][0][(i*d2+j)*d3];
for (int k=0; k<d3; ++k) {
m[i][j][k]=0.0;
}
}
}
+或-也就是说,您需要分配连续的d1*d2*d3块内存,然后将数组索引指向该连续内存中的适当位置。
相关文章:
- 如何计算 3d 数组中的索引值在内存中的位置?如何计算字符**中的索引值在内存中的位置?
- 我是 c++ 的新手,有没有一种算法可以找到 3d 数组中最接近的 0 的距离?
- 如何用零填充 3D 数组?
- 将长度可变的 C99 静态 3D 数组传递给函数
- C :将矢量重新为3D数组
- 将动态 3D 数组发送到 C++ 中的函数
- C++ 3D 数组到 1D 会导致堆缓冲区溢出
- 初始化const 3D数组成员变量
- 处理3D数组的边缘和角案例的方法
- 将2D数组的实例分配给3D数组中的索引
- 使用 vector 在 c++ 中声明 3D 数组结构
- 为什么C CHAR数据类型3D数组通过参数第一个括号为空白
- 可以使用 std::copy 将 3D 数组复制到矢量
- 我的重载 [] 运算符不适用于伪 3D 数组
- 从 3D 数组转换为 1D 数组失败
- 如何将3D .OBJ对象表示为3D数组
- 如何在C++中定义每个维度具有不同类型的 3D 数组
- CPP 3D 动态创建由单个内存块组成的 3D 数组
- 视觉读取列文本数据并在C++中放入 3D 数组
- 将 3D 数组的索引传递给函数