C++11 MPI-使用多个线程侦听传入消息

C++11 MPI-使用多个线程侦听传入消息,c++11,mpi,openmpi,C++11,Mpi,Openmpi,我正在从事一个使用MPI例程和多线程发送和接收消息的项目。我希望每个接收线程都关注不同的传入消息,而不是让两个或多个线程尝试接收相同的消息。有没有办法做到这一点 我不知道这是否有帮助,但我目前正在使用Iprobe()检查传入消息,并使用Irecv()和Test()检查线程是否已接收到整个消息。如果我理解正确,则问题不在于您如何接收消息,而在于您如何发送消息。正如您在下面看到的MPI_Send函数具有destination参数,该参数定义了此消息将发送到哪个线程 MPI_Send( voi

我正在从事一个使用MPI例程和多线程发送和接收消息的项目。我希望每个接收线程都关注不同的传入消息,而不是让两个或多个线程尝试接收相同的消息。有没有办法做到这一点


我不知道这是否有帮助,但我目前正在使用Iprobe()检查传入消息,并使用Irecv()和Test()检查线程是否已接收到整个消息。

如果我理解正确,则问题不在于您如何接收消息,而在于您如何发送消息。正如您在下面看到的
MPI_Send
函数具有
destination
参数,该参数定义了此消息将发送到哪个线程

MPI_Send(
    void* data,
    int count,
    MPI_Datatype datatype,
    int destination,
    int tag,
    MPI_Comm communicator)

因此,如果要使某些线程接收某些消息,则必须仅将这些消息发送给该线程。

从标准的第3版开始,MPI允许从消息队列中删除匹配的消息,以便后续探测/接收不再看到这些消息。这是使用所谓的匹配探针完成的。只需将
MPI_Iprobe
替换为
MPI_Improbe
,这是非阻塞匹配探针操作:

int flag;
MPI_Status status;
MPI_Message msg;

MPI_Improbe(source, tag, comm, &flag, &msg, &status);
一旦
MPI\u Improbe
标志中返回1,匹配
(源、标记、通信)
的消息就到达了。消息的句柄存储在
msg
中,消息将从队列中删除。同一线程或另一线程使用匹配的三元组(source、tag、comm)进行后续探测或接收时,不会再次看到相同的消息,因此不会干扰最初匹配该消息的线程的接收

要接收匹配的消息,请使用
MPI\u Imrecv
(或阻塞
MPI\u Mrecv
):

3.0之前的MPI版本不提供类似的功能。但是,如果我理解正确,您只需保证在
MPI_Irecv
有机会从队列中删除消息之前不会发布匹配的探测(这就是匹配探测+接收的目的)。如果在主线程中进行探测,然后将消息分派到不同的线程,那么可以使用信号量延迟主线程执行下一个探测,直到工作线程发出
MPI\u Irecv
之后。如果您有多个线程执行probe+receive,那么在探测成功后,您只需在同一关键部分(或用于实现MPI线程序列化所需的MPI调用序列化的任何同步原语)中发出
MPI\u Irecv
调用即可:

// Worker thread
CRITICAL(mpi)
{
  MPI_Iprobe(source, tag, comm, &flag, &status);
  if (flag)
    MPI_Irecv(buffer, count, dtype, status.MPI_SOURCE, status.MPI_TAG, comm, &req);
}

用编程环境提供的原语替换
CRITICAL(name){…}
符号。

但目标是接收消息的MPI进程的级别,而不是该进程中的线程,对吗?请记住,如果可能,MPI进程在每个单线程上运行。所以,在双核环境中,您将在单独的线程上有两个进程。当你有比踏板更多的进程时,问题就开始了,然后其中一些进程将在彼此之间共享线程。我道歉,因为我认为我没有把我的问题说清楚。发送线程不应该知道接收线程的数量或它们在接收进程上的ID。接收过程的级别应该足够。我真正想知道的是,是否有一种接收进程的方法来检测其中一个进程是否已开始接收传入消息(使其处于“忙”状态),以便其他进程(处于“空闲”状态)可以处理其余的传入消息。顺便说一句,我使用的是MPI\u线程\u序列化支持级别,因为我在OpenMPI文档中读到MPI\u线程\u MULTIPLE尚未经过彻底测试,但感谢您的建议。我明白了,那么您应该实际使用MPI-3非阻塞匹配探测(
MPI\u Improbe
)结合(非阻塞)匹配接收(
MPI(I)mrecv
)。匹配操作会在消息队列中隐藏匹配后的消息。我会相应地更新答案。谢谢你,那一定正是我想要的。是的,请更新您的答案,以便我可以接受。还有一件事:我可以使用匹配的操作,但你说它们在MPI-3中,我想提供与以前版本一起工作的代码。你知道使用MPI3之前的例程实现这一点的方法吗?@George,好了,我已经用你可能需要的替换了整个答案。
// Worker thread
CRITICAL(mpi)
{
  MPI_Iprobe(source, tag, comm, &flag, &status);
  if (flag)
    MPI_Irecv(buffer, count, dtype, status.MPI_SOURCE, status.MPI_TAG, comm, &req);
}