gpt4 book ai didi

c++ - MPI_send MPI_recv 在增加 arry 大小时失败

转载 作者:行者123 更新时间:2023-11-30 01:16:09 25 4
gpt4 key购买 nike

我正在尝试使用 OpenMPI 1.6.4 版编写 3D 并行计算泊松求解器。

以下部分是我使用阻塞发送接收进行并行计算的代码。

在另一个文件中声明了以下变量。

int px = lx*meshx; //which is meshing point in x axis.
int py = ly*meshy;
int pz = lz*meshz;
int L = px * py * pz

下面的代码运行良好,而

lx=ly=lz=10;

meshx=meshy=2, meshz=any int number.

当 meshx 和 meshy 大于 4 时发送接收部分失败。

卡在那里等待发送或接收数据的程序。

但如果我只将数据从一个处理器发送到另一个处理器,而不交换数据,它就可以工作。(即:从等级 0 发送到 1,但不要从 1 发送到 0)

我无法理解这段代码在 meshx 和 meshy 很小的时候是如何工作的,但是在网格数 x y 很大的时候失败了。

阻塞发送接收进程是否会中断自身,或者我在代码中混淆了处理器?这与我的数组大小有关系吗?

#include "MPI-practice.h"

# include <iostream>
# include <math.h>
# include <string.h>
# include <time.h>
# include <sstream>
# include <string>

# include "mpi.h"


using namespace std;


extern int px,py,pz;
extern int L;
extern double simTOL_phi;
extern vector<double> phi;

int main(int argc, char *argv[]){

int numtasks, taskid, offset_A, offset_B, DD_loop,s,e;
double errPhi(0),errPhi_sum(0);

MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
MPI_Comm_rank(MPI_COMM_WORLD, &taskid);
MPI_Status status;

if((pz-1)%numtasks!=0){
//cerr << "can not properly divide meshing points."<<endl;
exit(0);
}

offset_A=(pz-1)/numtasks*px*py;
offset_B=((pz-1)/numtasks+1)*px*py;

s=offset_A*taskid;
e=offset_A*taskid+offset_B;


int pz_offset_A=(pz-1)/numtasks;
int pz_offset_B=(pz-1)/numtasks+1;

stringstream name1;
string name2;

Setup_structure();
Initialize();
Build_structure();

if (taskid==0){
//master processor

ofstream output;
output.open("time", fstream::out | fstream::app);
output.precision(6);

clock_t start,end;

start=clock();

do{
errPhi_sum=0;

errPhi=Poisson_inner(taskid,numtasks,pz_offset_A,pz_offset_B);
//Right exchange

MPI_Send(&phi[e-px*py], px*py, MPI_DOUBLE, taskid+1, 1, MPI_COMM_WORLD);
MPI_Recv(&phi[e], px*py, MPI_DOUBLE, taskid+1, 1, MPI_COMM_WORLD, &status);

MPI_Allreduce ( &errPhi, &errPhi_sum, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD );

}while(errPhi_sum>simTOL_phi);

end=clock();
output << "task "<< 0 <<" = "<< (end-start)/CLOCKS_PER_SEC <<endl<<endl;

Print_to_file("0.txt");

//recv from slave
for (int i=1;i<numtasks;i++){
MPI_Recv(&phi[offset_A*i], offset_B, MPI_DOUBLE, i, 1, MPI_COMM_WORLD, &status);
}

Print_to_file("sum.txt");

}
else{
//slave processor

do{

errPhi=Poisson_inner(taskid,numtasks,pz_offset_A,pz_offset_B);

//Left exchange
MPI_Send(&phi[s+px*py], px*py, MPI_DOUBLE, taskid-1, 1, MPI_COMM_WORLD);
MPI_Recv(&phi[s], px*py, MPI_DOUBLE, taskid-1, 1, MPI_COMM_WORLD, &status);



//Right exchange
if(taskid!=numtasks-1){
MPI_Send(&phi[e-px*py], px*py, MPI_DOUBLE, taskid+1, 1, MPI_COMM_WORLD);
MPI_Recv(&phi[e], px*py, MPI_DOUBLE, taskid+1, 1, MPI_COMM_WORLD, &status);
}

MPI_Allreduce ( &errPhi, &errPhi_sum, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD );

}while(errPhi_sum>simTOL_phi);

//send back master
MPI_Send(&phi[s], offset_B, MPI_DOUBLE, 0, 1, MPI_COMM_WORLD);

name1<<taskid<<".txt";
name2=name1.str();
Print_to_file(name2.c_str());


}

MPI_Finalize();
}

最佳答案

将所有耦合的 MPI_Send/MPI_Recv 调用替换为对 MPI_Sendrecv 的调用。比如这个

MPI_Send(&phi[e-px*py], px*py, MPI_DOUBLE, taskid+1, 1, MPI_COMM_WORLD);
MPI_Recv(&phi[e], px*py, MPI_DOUBLE, taskid+1, 1, MPI_COMM_WORLD, &status);

成为

MPI_Sendrecv(&phi[e-px*py], px*py, MPI_DOUBLE, taskid+1, 1,
&phi[e], px*px, MPI_DOUBLE, taskid+1, 1,
MPI_COMM_WORLD, &status);

MPI_Sendrecv 在内部使用非阻塞操作,因此它不会死锁,即使两个等级同时相互发送也是如此。唯一的要求(像往常一样)是每次发送都与接收相匹配。

关于c++ - MPI_send MPI_recv 在增加 arry 大小时失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27173722/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com