【问题标题】:Timeline of asynchronous MPI communication异步 MPI 通信的时间线
【发布时间】:2014-08-23 17:20:09
【问题描述】:

要优化 MPI 通信,了解整个通信过程的流程很重要。这对于同步通信来说相当简单,但是异步通信呢?据我了解,它以以下两种方式之一工作:

  1. Rank0 -> Isend -> Rank1 和 Rank1 -> Isend -> Rank0
  2. Rank0 -> Irecv -> Rank1 和 Rank1 -> Irecv -> Rank0
  3. Rank0 和 Rank1 进行一些计算
  4. 消息正在发送到各自的目标位置
  5. 找到匹配的 Recv 调用! -> 写入给定的接收缓冲区
  6. Rank0 和 Rank1 完成计算并调用 MPI_Wait 进行发送和接收
  7. MPI_Wait -> 通信完成

  1. Rank0 -> Isend -> Rank1 和 Rank1 -> Isend -> Rank0
  2. Rank0 和 Rank1 进行一些计算
  3. 消息正在发送到各自的目标位置
  4. 未找到匹配的 Recv 调用! -> 分配自己的临时缓冲区并写入其中
  5. Rank0 和 Rank1 完成计算并调用 MPI_Recv
  6. 找到匹配的 MPI_Recv 调用 -> 将临时缓冲区写入recv-buffer
  7. Rank0 和 Rank1 调用 MPI_Wait
  8. MPI_Wait -> 通信完成 -> 释放临时缓冲区

这是正确的吗?我是否需要了解在 MPI 后台运行的任何其他进程以优化其使用?

【问题讨论】:

    标签: asynchronous mpi


    【解决方案1】:

    一般来说,当使用 MPI 发送数据时,如果可能,您应该始终预先发布您的接收数据。这意味着如果您尝试在两个进程之间进行通信,您应该这样做(为简洁起见,省略了许多重要的参数):

    if (rank == 0) {
      MPI_Irecv(rdata, ..., 1, ..., req[0]);
      ...
      MPI_Isend(sdata, ..., 1, ..., req[1]);
    } else {
      MPI_Irecv(rdata, ..., 0, ..., req[0]);
      ...
      MPI_Isend(sdata, ..., 0, ..., req[1]);
    }
    MPI_Waitall(2, req);
    

    如果您愿意,您可以在 IrecvIsend 之间做其他事情,但是通过预先发布接收,您将节省内存和时间,因为 MPI 库可以使用用户缓冲区来放置如果您不按此顺序执行此操作,并且消息在您调用 Irecv(或任何其他类型的接收)之前到达,则必须先将消息存储在其他内部缓冲区中,直到接收发布后,消息将再次从 MPI 缓冲区复制到用户缓冲区。如果消息太大而无法放入预分配的缓冲区,这也可能导致在调用接收之前根本不会发送消息。

    您也可以尽早致电Irecv。如果你想把Irecv放在一个迭代的开始,做一堆计算,然后在迭代结束时,数据准备好时调用Isend,也可以。

    除非您有很多进程向一个进程发送消息,否则其他进程之间的串扰通常不是问题。在这种情况下,您最终可能会遇到一些流量控制问题,但这通常不会出现。大多数时候在这种情况下,使用集体而不是点对点通信。

    【讨论】:

    • 你说用户缓冲区会及时可用,但是如果数据是在Isend上发送的,那么调用Irecv,然后Isend然后做一些计算不是最有效的(而不是Irecv - > calc -> Isend)?
    • 这完全取决于您的应用。我在示例中的假设是您正在执行某种迭代应用程序,其中每个循环都进行一些计算,与邻居交换一些数据并重复。在这种情况下,我上面所说的效果很好。如果你正在做一些其他的模式,那也很好。要点是您应该预先发布您的收据。其他一切都取决于您的应用。
    猜你喜欢
    • 2020-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-17
    • 1970-01-01
    • 2019-09-15
    • 1970-01-01
    • 2013-02-07
    相关资源
    最近更新 更多