有办法取消阻塞的“ MPI_Probe”调用吗?

时间:2019-11-19 16:28:51

标签: mpi

MPI_IrecvMPI_Isend操作返回一个MPI_Request,以后可以使用MPI_Cancel将其标记为已取消。是否有类似的机制来阻止MPI_ProbeMPI_Mprobe

问题的上下文是Boost.MPI request handlers使用Probe的最新实现。


编辑-这是一个如何使用假设的MPI_Probecancel的示例:

#include <mpi.h>

#include <chrono>
#include <future>

using namespace std::literals::chrono_literals;

// Executed in a thread
void async_cancel(MPI_Probe *probe)
{
  std::this_thread::sleep_for(1s);

  int res = MPI_Probecancel(probe);
}

int main(int argc, char* argv[])
{
  int provided;
  MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided);

  if (rank == 0)
  {
    // A handle to the probe (similar to a request)
    MPI_Probe probe;

    // Start a thread
    // `probe` will be filled with the next call, pretty ugly
    // Ideally, this should be done in two steps like MPI_Irecv, MPI_Wait
    auto res = std::async(std::launch::async, &async_cancel, &probe);

    MPI_Message message;
    MPI_Status status;
    MPI_MProbe(1, 123, MPI_COMM_WORLD, &message, &status, &probe);

    if (!probe.cancelled)
    {
        int buffer;
        MPI_Mrecv(&buffer, 1, MPI_INT, &message, &status);
    }
  }
  else
    std::this_thread::sleep_for(2s);

  MPI_Finalize();
  return 0;
}

1 个答案:

答案 0 :(得分:0)

首先,您的问题的前提/术语是错误的。这是 nonblocking 调用。 MPI_IrecvMPI_Isend返回您可以取消的请求对象。对于这些呼叫,您可以取消本地操作

MPI_ProbeMPI_Mprobe实际上是屏蔽。就控制流只会在消息可用时离开而言,您不可能取消这些操作。

另一方面,MPI_IprobeMPI_Improbe无阻塞的,这意味着它们总是立即完成,告诉您是否可用消息。

对于这两种类型的探测调用,完成后都没有剩下任何一种本地状态。因此,在函数返回后,没有什么可以在本地取消。

也就是说,如果探针告诉您消息可用,那么您肯定应该收到它。否则,发送操作可能会停止,并且您将全方位泄漏资源。但这只是一个接收操作。

编辑:关于取消并发线程中正在进行的本地MPI_Probe的想法:不直接支持。

从理论上讲,您可以通过在MPI_THREAD_MULTIPE上运行探针,并从另一个线程向同一级别发送消息,来在符合MPI_ANY_SOURCE的标准实现上对此进行仿真。当然,这样做的结果是,您必须更改任何传入级别的邮件。

实际上,如果必须执行此操作,则可能只使用while(!cancelled) MPI_Iprobe();之类的循环。

也就是说,我会再次质疑这种情况:您所在级别上的另一个线程如何突然知道取消本地MPI_Probe操作?它可能必须基于从远程等级接收到的信息-在这种情况下,实际上可以从中接收信息,即实际的探测将完成。

也许对于某些高级抽象而言,提供局部取消是有意义的,但是在实际实际情况下,我认为您可以设计惯用模式而无需这样做。