我的MPI算法有什么问题吗?

时间:2013-08-07 21:32:46

标签: fortran mpi

我设置这个算法在不同的处理器之间共享数据,到目前为止它已经工作了,但我试图在它上面抛出一个更大的问题,我正在目睹一些非常奇怪的行为。我正在丢失MPI_Isend和MPI_Recv之间的数据。

我提供了以下代码的片段。它基本上由三个阶段组成。首先,处理器将遍历给定数组中的所有元素。每个元素代表网格中的一个单元格。处理器检查该元素是否正在其他处理器上使用。如果是,则使用单元格的唯一全局ID作为标记对该进程执行非阻塞发送。如果不是,则检查下一个元素,依此类推。

其次,处理器然后再次遍历所有元素,这次检查处理器是否需要更新该单元中的数据。如果是,则数据已由另一个进程发送出去。当前进程只是执行阻塞接收,知道谁拥有数据以及该单元的唯一全局ID。

最后,MPI_Waitall用于在非阻塞发送期间存储在'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)

2 个答案:

答案 0 :(得分:1)

您的问题是您没有收到所有邮件吗?请注意,仅仅因为MPI_SEND或MPI_ISEND完成,并不意味着相应的MPI_RECV实际上已发布/完成。返回发送调用仅意味着发送方可以重用缓冲区。该数据仍然可以在发送方或接收方的某处内部缓冲。

如果知道邮件实际收到是至关重要的,则需要使用不同类型的发送,如MPI_SSEND或MPI_RSEND(如果您愿意,还可以使用非阻止版本)。请注意,这实际上不会解决您的问题。它可能会让您更容易找出哪些消息没有显示出来。

答案 1 :(得分:0)

我找到了让代码运行的方法,但我不完全确定原因,所以我将在这里发布解决方案,也许有人可以评论为什么会出现这种情况并可能提供更好的解决方案溶液

正如我在问题中指出的那样,正如我们在评论中所讨论的那样,发送/接收之间似乎丢失了一些数据。缓冲区的概念对我来说是一个谜,但我认为可能没有足够的空间来容纳我的Isends,允许它们在收到之前迷路。所以我用MPI_Bsend调用换掉了MPI_Isend调用。我弄清楚我的缓冲区需要多大才能使用MPI_Pack_size。这样,我知道我将为我发送的所有邮件提供充足的空间。我使用MPI_Buffer_attach分配我的缓冲区大小。我摆脱了MPI_Waitall,因为它不再需要了,我用MPI_Buffer_detach调用替换它。

代码运行没有问题,并且在串行情况下得到相同的结果。我能够将问题的大小扩展到我之前尝试过的,现在可以正常工作了。因此,基于这些结果,我必须假设由于缓冲区空间不足而丢失了一些消息。

我担心对代码性能的影响。我对不同的问题规模进行了扩展研究。见下图。 x轴给出问题的大小(5表示问题是1的5倍)。 y轴给出了完成程序执行的时间。显示了三行。串行运行程序显示为蓝色。 size = 1的情况用绿线线性外推。我们看到代码执行时间与问题大小线性相关。红线表示并行运行程序---我们使用了许多与问题大小相匹配的处理器(例如,2个核心用于大小= 2,4个核心用于大小= 4等)。

您可以看到并行执行时间随着问题大小的增加而非常缓慢,这是预期的,除了最大的情况。我觉得最大案例的糟糕表现是由于消息缓冲量的增加造成的,这在较小的情况下是不需要的。

enter image description here