MPI中的持久通信-奇数行为

MPI中的持久通信-奇数行为,mpi,nonblocking,Mpi,Nonblocking,我正在使用jacobi迭代和非阻塞调用MPI_Isend()和MPI_Irecv()求解并行几何多重网格的最粗网格。这方面没有问题。一旦我用持久通信替换了非阻塞通信,结果就在这个级别停止收敛,程序进入无限循环。调用MPI\u Startall()和MPI\u Waitall()始终返回MPI\u SUCCESS。以前有人遇到过这个问题吗?请告知 Coarsest_grid_solve() { MPI_Recv_init(&e_c_old[0][1][1], 1, x_subarray_

我正在使用jacobi迭代和非阻塞调用
MPI_Isend()
MPI_Irecv()
求解并行几何多重网格的最粗网格。这方面没有问题。一旦我用
持久通信
替换了非阻塞通信,结果就在这个级别停止收敛,程序进入无限循环。调用
MPI\u Startall()
MPI\u Waitall()
始终返回
MPI\u SUCCESS
。以前有人遇到过这个问题吗?请告知

 Coarsest_grid_solve()
{
MPI_Recv_init(&e_c_old[0][1][1], 1, x_subarray_c, X_DOWN, 10, new_comm, &recv[0]);
MPI_Recv_init(&e_c_old[PXC+1][1][1], 1, x_subarray_c, X_UP, 20, new_comm, &recv[1]);
MPI_Recv_init(&e_c_old[1][PYC+1][1], 1, y_subarray_c, Y_RIGHT, 30, new_comm, &recv[2]);
MPI_Recv_init(&e_c_old[1][0][1], 1, y_subarray_c, Y_LEFT, 40, new_comm, &recv[3]); 
MPI_Recv_init(&e_c_old[1][1][PZC+1], 1, z_subarray_c, Z_AWAY_U, 50, new_comm, &recv[4]);
MPI_Recv_init(&e_c_old[1][1][0], 1, z_subarray_c, Z_TOWARDS_U, 60, new_comm, &recv[5]);

MPI_Send_init(&e_c_old[PXC][1][1], 1, x_subarray_c, X_UP, 10, new_comm, &send[0]);
MPI_Send_init(&e_c_old[1][1][1], 1, x_subarray_c, X_DOWN, 20, new_comm, &send[1]);
MPI_Send_init(&e_c_old[1][1][1], 1, y_subarray_c, Y_LEFT, 30, new_comm, &send[2]);
MPI_Send_init(&e_c_old[1][PYC][1], 1, y_subarray_c, Y_RIGHT, 40, new_comm, &send[3]);
MPI_Send_init(&e_c_old[1][1][1], 1, z_subarray_c, Z_TOWARDS_U, 50, new_comm, &send[4]);
MPI_Send_init(&e_c_old[1][1][PZC], 1, z_subarray_c, Z_AWAY_U, 60, new_comm, &send[5]);  

while(rk_global/r0_global > TOL_CNORM)              
{
coarse_iterations++ ;           

err = MPI_Startall(6,recv);
if(err == MPI_SUCCESS)
    printf("success");

err = MPI_Startall(6,send);
if(err == MPI_SUCCESS)
    printf("success");

err = MPI_Waitall(6, send, MPI_STATUSES_IGNORE);
if(err == MPI_SUCCESS)
    printf("success");

err = MPI_Waitall(6, recv, MPI_STATUSES_IGNORE);
if(err == MPI_SUCCESS)
    printf("success");

//do work here

if(coarse_iterations == 1)
{
    update_neumann_c(e_c_old, PXC, PYC, PZC, X_UP, Y_RIGHT, Z_AWAY_U);
    residual_coarsest(e_c_old, rho_c, PXC, PYC, PZC, X_UP, Y_RIGHT, Z_AWAY_U, hc, rho_temp); 
    r0_local = residual_norm(rho_temp, PXC, PYC, PZC); 
    start_allred = MPI_Wtime();
    MPI_Allreduce(&r0_local, &r0_global, 1, MPI_DOUBLE, MPI_SUM, new_comm); 
    end_allred = MPI_Wtime(); 
    r0_global = r0_global/( (PXC*dims0) * (PYC*dims1) * (PZC*dims2) ); 
    if(rank == 0)
        printf("\nGlobal residual norm is = %f", r0_global);
    rk_global = r0_global;
}           
else
{
    update_neumann_c(e_c_old, PXC, PYC, PZC, X_UP, Y_RIGHT, Z_AWAY_U);
    residual_coarsest(e_c_old, rho_c, PXC, PYC, PZC, X_UP, Y_RIGHT, Z_AWAY_U, hc, rho_temp); 
    rk_local = residual_norm(rho_temp, PXC, PYC, PZC);
    start_allred = MPI_Wtime(); 
    MPI_Allreduce(&rk_local, &rk_global, 1, MPI_DOUBLE, MPI_SUM, new_comm);
    end_allred = MPI_Wtime();  
    rk_global = rk_global/( (PXC*dims0) * (PYC*dims1) * (PZC*dims2) );
    if(rank == 0)
        printf("\nGlobal residual norm is = %f", rk_global);
}

//do dependent work and exchange matrices
}//while loop ends

for(i = 0; i <= 5 ; i++)
{
    MPI_Request_free(&send[i]);
    MPI_Request_free(&recv[i]);
}
}//End coarsest grid solve
最粗网格求解()
{
MPI_Recv_init(&e_c_old[0][1][1],1,x_子阵,x_DOWN,10,new_comm,&Recv[0]);
MPI_Recv_init(&e_c_old[PXC+1][1][1],1,x_子阵列c,x_UP,20,新通信,&Recv[1]);
MPI_Recv_init(&e_c_old[1][PYC+1][1],1,y_子阵,y_RIGHT,30,new_comm,&Recv[2]);
MPI_Recv_init(&e_c_old[1][0][1],1,y_子阵,y_LEFT,40,new_comm,&Recv[3]);
MPI_Recv_init(&e_c_old[1][1][PZC+1],1,z_子阵列,z_AWAY_,50,new_comm,&Recv[4]);
MPI_Recv_init(&e_c_old[1][1][0],1,z_子阵,z_向_,60,新_通信,&Recv[5]);
MPI_Send_init(&e_c_old[PXC][1][1],1,x_子阵列_c,x_UP,10,new_comm,&Send[0]);
MPI_Send_init(&e_c_old[1][1][1],1,x_子阵列,x_DOWN,20,new_comm,&Send[1]);
MPI_Send_init(&e_c_old[1][1][1],1,y_子阵列_c,y_LEFT,30,new_comm,&Send[2]);
MPI_Send_init(&e_c_old[1][PYC][1],1,y_子阵列_c,y_RIGHT,40,new_comm,&Send[3]);
MPI_Send_init(&e_c_old[1][1][1],1,z_子阵列_c,z_朝向_,50,新_comm,&Send[4]);
MPI_Send_init(&e_c_old[1][1][PZC],1,z_子阵列_c,z_AWAY_,60,new_comm,&Send[5]);
而(rk_global/r0_global>TOL_CNORM)
{
粗_迭代++;
err=MPI_标准高度(6,recv);
如果(错误==MPI\U成功)
printf(“成功”);
err=MPI_Startall(6,发送);
如果(错误==MPI\U成功)
printf(“成功”);
err=MPI_Waitall(6,发送,MPI_状态\u忽略);
如果(错误==MPI\U成功)
printf(“成功”);
err=MPI_Waitall(6,recv,MPI_状态\u忽略);
如果(错误==MPI\U成功)
printf(“成功”);
//你在这里工作吗
if(粗略迭代==1)
{
更新neumann_c(e_c_old,PXC,PYC,PZC,X_UP,Y_RIGHT,Z_AWAY_);
最粗糙的残余物(e_c_旧、rho_c、PXC、PYC、PZC、X_上、Y_右、Z_远、hc、rho_温度);
r0_局部=剩余_范数(rho_温度、PXC、PYC、PZC);
start_allred=MPI_Wtime();
MPI\u Allreduce(&r0\u本地,&r0\u全局,1,MPI\u双精度,MPI\u总和,新通信);
end_allred=MPI_Wtime();
r0_global=r0_global/(PXC*dims0)*(PYC*dims1)*(PZC*dims2));
如果(秩==0)
printf(“\n全局剩余范数=%f”,r0\u全局);
rk_global=r0_global;
}           
其他的
{
更新neumann_c(e_c_old,PXC,PYC,PZC,X_UP,Y_RIGHT,Z_AWAY_);
最粗糙的残余物(e_c_旧、rho_c、PXC、PYC、PZC、X_上、Y_右、Z_远、hc、rho_温度);
rk_local=剩余_范数(rho_temp,PXC,PYC,PZC);
start_allred=MPI_Wtime();
MPI\u Allreduce(本地和全局,1,MPI\u双精度,MPI\u总和,新通信);
end_allred=MPI_Wtime();
rk_global=rk_global/(PXC*dims0)*(PYC*dims1)*(PZC*dims2));
如果(秩==0)
printf(“\n全局剩余范数=%f”,rk_全局);
}
//做相关的工作,交换矩阵
}//当循环结束时

对于(i=0;i当我们为通信创建一个持久句柄时,我们指向一个特定的内存块,我们希望将它转移到其他进程。现在在Jacobi迭代中,我们需要在迭代结束时交换指针,使旧矩阵指向新的更新矩阵。因此,指针指向的内存位置会发生变化。因此,原始位置被交换。解决方法是定义两个持久通信句柄。奇数次迭代使用第一个句柄,偶数次迭代使用另一个句柄,即交替使用。这解决了我的问题。这个问题也拓宽了我对MPI中持久通信的理解。

抱歉-刚刚编辑了一个nd添加了相关代码。我想这是因为我在执行Jacobi迭代,并在末尾交换指向不同矩阵的指针-它只在指针指向原始矩阵时传递数据。是的,
MPI\u Yyy\u init
的缓冲区参数会记住我的MPI,然后对所有矩阵使用相同的缓冲区arted communications。你自己学会了这一点很好。一个建议——在将来发布问题时,尝试首先将你的问题提炼成一个小的、功能齐全的示例代码,该代码仍然可以重现问题,并且可以由SO的成员编译和测试。通常,你会在这样做时自己找到解决方案,并且如果没有,你将使那些试图回答你问题的人的生活变得更轻松。非常感谢你的确认和建议。我将从现在开始遵循它。