【发布时间】:2016-12-10 05:12:02
【问题描述】:
我使用 MPI 实现了一个简单的 1D Poisson 方程并行求解器,因此请熟悉 MPI 库。我将代码设计为使用未指定数量的处理器(包括只有 1 个)运行。
代码在 1 或 2 个处理器上运行并产生良好的结果。但是,它会卡在带有 4 个处理器的 mpi_send 和 mpi_recv 调用上。因此,我预计我的鬼点交换的实现是错误的。
由于代码太大,这里无法包含,我只包含了 Jacobi 方案和数据交换:
do iter=1,max_iter
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Initial guess, on interior points only
Ujacob(min_x+1:max_x-1) = 0._dp
Ujacob_all(0:grid_nx-1) = 0._dp
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Store solution vector from last iteration
Uold (:) = Ujacob (:)
Uold_all(:) = Ujacob_all(:)
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Jacobi scheme
do ii=min_x+1,max_x-1
!Ujacob(ii) = 0.5_dp * (Uold (ii-1) + Uold (ii+1) - grid_delta_x**2 * Urhs(ii))
end do
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Gather Ujacob vector
call mpi_allgather(Ujacob(0:proc_nx-1), proc_nx, mpi_float, &
& Ujacob_all, proc_nx, mpi_float, mpi_comm_world, ierror)
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Compute error and check if less than tolerance value
error = sqrt((sum(Ujacob_all - Uold_all)**2) / dble(grid_nx))
if(error < error_tol) return
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Exchange data points
! Interior processors
if(Xsrc /= -1 .AND. Xdes /= -1) then
call mpi_send(Ujacob( 0), 1, mpi_float, Xsrc, 200, mpi_comm_world, ierror)
call mpi_send(Ujacob(proc_nx-1), 1, mpi_float, Xdes, 100, mpi_comm_world, ierror)
call mpi_recv(Ujacob( -1), 1, mpi_float, Xsrc, 100, mpi_comm_world, stat, ierror)
call mpi_recv(Ujacob(proc_nx), 1, mpi_float, Xdes, 200, mpi_comm_world, stat, ierror)
! First processor
elseif(Xsrc == -1) then
call mpi_send(Ujacob(proc_nx-1), 1, mpi_float, Xdes, 100, mpi_comm_world, ierror)
call mpi_recv(Ujacob(proc_nx ), 1, mpi_float, Xdes, 200, mpi_comm_world, stat, ierror)
! Last processor
elseif(Xdes == -1) then
call mpi_send(Ujacob( 0), 1, mpi_float, Xsrc, 200, mpi_comm_world, ierror)
call mpi_recv(Ujacob(-1), 1, mpi_float, Xsrc, 100, mpi_comm_world, stat, ierror)
end if
end do
Xsrc 和 Xdes 设置如下:
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Setting the source and destination neighbors of each processor
if(myid == 0) then
Xsrc = -1
Xdes = myid + 1
elseif(myid == nprocs-1) then
Xsrc = myid -1
Xdes = -1
else
Xsrc = myid - 1
Xsrc = myid + 1
end if
另外,我检查了处理器等级 0 和 nprocs-1 确实对应于左右边界处理器。
我已检查标签是否设置正确。另外,请随时评论您认为可以改进的任何内容。
【问题讨论】:
-
我认为看看你如何设置
Xsrc和Xdes可能会有用。 -
@d_1999 是的,你是对的,请查看编辑
-
您的光环交换在概念上存在缺陷,因为您依赖
MPI_SEND被缓冲,但情况可能并非总是如此。使用MPI_SENDRECV可以同时发送和接收,不会阻塞。另外,不要使用如此复杂的逻辑进行发送和接收。只需使用MPI_PROC_NULL而不是-1用于边界等级的不存在的邻居,并始终在两个方向上执行sendrecv。发送到MPI_PROC_NULL或从它接收是无操作的。 -
我认为您在编辑的最后一个分支中有错字。
-
计算速度很快,但通信速度却不是这样。您不会看到小型数组的任何加速。
标签: parallel-processing fortran mpi