我设置了这个算法来在不同的处理器之间共享数据,到目前为止它一直有效,但我试图给它抛出一个更大的问题,我正在目睹一些非常奇怪的行为。我在 MPI_Isend 和 MPI_Recv 之间丢失了一些数据。
我在下面展示了一段代码。它基本上由三个阶段组成。首先,处理器将遍历给定数组中的所有元素。每个元素代表网格中的一个单元。处理器检查该元素是否正在其他处理器上使用。如果是,它使用单元的唯一全局 ID 作为标签向该进程进行非阻塞发送。如果否,则检查下一个元素,依此类推。
其次,处理器然后再次循环遍历所有元素,这一次检查处理器是否需要更新该单元格中的数据。如果是,那么数据已经被另一个进程发送出去了。当前进程只是进行阻塞接收,知道谁拥有数据和该单元的唯一全局 ID。
最后,MPI_Waital 用于在非阻塞发送期间存储在“req”数组中的请求代码。
我遇到的问题是整个过程完成了——代码没有挂起。但是某些单元接收的某些数据是不正确的。我通过在发送操作之前打印每条数据来检查发送的所有数据是否正确。请注意,我正在发送和接收数组的一部分。每次发送将传递 31 个元素。当我从接收它的进程打印数组时,31 个元素中有 3 个是垃圾。所有其他元素都是正确的。奇怪的是,垃圾总是相同的三个元素——第一个、第二个和最后一个元素。
我想排除我的算法中没有严重错误可以解释这一点。或者它可能与我正在处理的集群有关?正如我所提到的,这适用于我扔给它的所有其他模型,最多使用 31 个内核。当我尝试将 56 个内核用于解决问题时,我遇到了这种行为。如果没有出现任何错误,您能否建议一种方法来测试为什么某些发送部分没有到达目的地?
do i = 1, num_cells
! skip cells with data that isn't needed by other processors
if (.not.needed(i)) cycle
tag = gid(i) ! The unique ID of this cell in the entire system
ghoster = ghosts(i) ! The processor that needs data from this cell
call MPI_Isend(data(i,1:tot_levels),tot_levels,mpi_datatype,ghoster,tag,MPI_COMM,req(send),mpierr)
send = send + 1
end do
sends = send-1
do i = 1, num_cells
! skip cells that don't need a data update
if (.not.needed_here(i)) cycle
tag = gid(i)
owner = owner(i)
call MPI_Recv(data(i,1:tot_levels),tot_levels,mpi_datatype,owner,tag,MPI_COMM,MPI_STATUS_IGNORE,mpierr)
end do
call MPI_Waitall(sends,req,MPI_STATUSES_IGNORE,mpierr)