MPI_Irecv
和MPI_Isend
操作返回一个MPI_Request
,以后可以使用MPI_Cancel
将其标记为已取消。是否有类似的机制来阻止MPI_Probe
和MPI_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;
}
答案 0 :(得分:0)
首先,您的问题的前提/术语是错误的。这是 nonblocking 调用。 MPI_Irecv
和MPI_Isend
返回您可以取消的请求对象。对于这些呼叫,您可以取消本地操作。
MPI_Probe
和MPI_Mprobe
实际上是屏蔽。就控制流只会在消息可用时离开而言,您不可能取消这些操作。
另一方面,MPI_Iprobe
和MPI_Improbe
是无阻塞的,这意味着它们总是立即完成,告诉您是否可用消息。
对于这两种类型的探测调用,完成后都没有剩下任何一种本地状态。因此,在函数返回后,没有什么可以在本地取消。
也就是说,如果探针告诉您消息可用,那么您肯定应该收到它。否则,发送操作可能会停止,并且您将全方位泄漏资源。但这只是一个接收操作。
编辑:关于取消并发线程中正在进行的本地MPI_Probe
的想法:不直接支持。
从理论上讲,您可以通过在MPI_THREAD_MULTIPE
上运行探针,并从另一个线程向同一级别发送消息,来在符合MPI_ANY_SOURCE
的标准实现上对此进行仿真。当然,这样做的结果是,您必须更改任何传入级别的邮件。
实际上,如果必须执行此操作,则可能只使用while(!cancelled) MPI_Iprobe();
之类的循环。
也就是说,我会再次质疑这种情况:您所在级别上的另一个线程如何突然知道取消本地MPI_Probe
操作?它可能必须基于从远程等级接收到的信息-在这种情况下,实际上可以从中接收信息,即实际的探测将完成。
也许对于某些高级抽象而言,提供局部取消是有意义的,但是在实际实际情况下,我认为您可以设计惯用模式而无需这样做。