1

我在不同的地方问过这个问题,包括 OpenMPI 邮件列表。到目前为止,我没有运气。因此,如果有人可以提供帮助,我将不胜感激,无论这个问题看起来多么愚蠢。

问题:

考虑在两个不同的处理器上运行的两个进程 A 和 B。没有其他进程运行。进程 A 有两条消息要发送,M1(大小:Large,标记 T1)和 M2(1 字节,标记 T2)。进程 B 使用 MPI_Probe 选择性地过滤和接收消息。当它没有 MPI_Recv 消息 M1 时,是否保证进程 B 仍然可以接收消息 M2?考虑进程A首先发送了M1。所有进程都是单线程的。

此外,OpenMPI 是否确保可以以任何顺序接收来自同一来源、带有相同标签的两条不同消息?

基本上,我想了解 OpenMPI 的系统缓冲区是否发挥了任何作用:如果一条消息设法填满它,那么可能永远不会收到来自同一源但带有另一个标签的另一条消息。正确的?

非常感谢您的任何想法。

德文德拉

4

1 回答 1

2

我在 Open MPI 用户列表上回复了您,但也会在此处发布,以防其他人发现它有用。我相信 Jeff Squyres 已经在 Open MPI 邮件列表中回答了您的问题,或者至少暗示了可能存在的问题。MPI 消息按照它们发送的顺序被接收,但只在特定的(标签、通信器)元组内。这基本上意味着:

  • 在同一个通信器中,如果它们带有不同的标签,您可能会收到乱序的消​​息;
  • 如果它们在不同的上下文(通信器)中通信,则带有相同标签的消息可能会被乱序接收。

但这里有一个问题:如果尚未发布发送操作,您将无法收到消息。如果您有两个连续的发送操作,您必须确保第一个不会永远阻塞。标准的 MPI 发送操MPI_Send​​作可以以多种方式实现(标准没有具体说明如何),但在大多数 MPI 实现中,它的行为类似于非常小的消息的缓冲发送和大型消息的同步发送。如果您的发件人进程中有以下两个调用:

MPI_Send(largedata, largecount, MPI_INT, dest, tag1, MPI_COMM_WORLD);
MPI_Send(smalldata, smallcount, MPI_INT, dest, tag2, MPI_COMM_WORLD);

可能会发生第一个MPI_Send实际上表现为同步的,即除非匹配的接收操作发布在接收方一侧,否则它不会返回。假设您的接收者代码是:

MPI_Probe(src, tag2, MPI_COMM_WORLD, &status);
MPI_Recv(largedata, largecount, MPI_INT, src, tag1, MPI_COMM_WORLD, &status);

这很可能会死锁,因为这MPI_Probe是一个阻塞调用,即它不会在匹配的发送被发布之前返回,即第二个MPI_Send必须执行,这只会在第一个发送返回后发生,但它不会发生,除非MPI_Recv在接收者被执行...我想你明白了

为了防止死锁,您可以修改发件人的代码以使用非阻塞发送:

MPI_Request req;
MPI_Isend(largedata, largecount, MPI_INT, dest, tag1, MPI_COMM_WORLD, &req);
MPI_Send(smalldata, smallcount, MPI_INT, dest, tag2, MPI_COMM_WORLD);
MPI_Wait(&req, MPI_STATUS_IGNORE);

使用非阻塞操作,发送调用立即返回,操作在后台继续,因此第二次发送将在此之后立即执行。现在会有两条待处理的消息,它们可以按任何顺序接收,因为它们带有不同的标签。

于 2012-10-01T08:16:49.400 回答