MPI - 使用多个线程侦听传入的消息

时间:2015-08-21 12:53:48

标签: c++11 mpi openmpi

我正在开发一个使用MPI例程和多个线程来发送和接收消息的项目。我希望每个接收线程专注于不同的传入消息,而不是让两个或更多尝试接收相同的消息。有没有办法实现这个目标?

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

2 个答案:

答案 0 :(得分:2)

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

int flag;
MPI_Status status;
MPI_Message msg;

MPI_Improbe(source, tag, comm, &flag, &msg, &status);

一旦MPI_Improbeflag中返回1,就会收到与(source, tag, comm)匹配的邮件。消息的句柄存储在msg中,消息将从队列中删除。随后的探测或接收匹配(源,标记,通信)三元组 - 通过相同的线程或在另一个线程中 - 不会再次看到相同的消息,因此不会通过匹配的线程干扰其接收它本来就是。

要接收匹配的邮件,请使用MPI_Imrecv(或阻止MPI_Mrecv):

MPI_Request req;
MPI_Imrecv(buffer, count, dtype, &msg, &req);
do
{
   ...
   MPI_Test(&req, &flag, &status);
}
while (!flag);

3.0之前的MPI版本不提供类似的功能。但是,如果我理解正确,您只需要保证在MPI_Irecv有机会从队列中删除消息之前不会发布匹配的探测(这与探测+接收相匹配是为了防止) 。如果您正在主线程中进行探测,然后将消息分派到不同的线程,那么您可以使用信号量来延迟主线程执行下一个探测,直到工作者发出MPI_Irecv之后。如果您有多个线程正在进行探测+接收,那么您可以简单地在同一个关键部分发出MPI_Irecv调用(或者您使用的任何同步原语,以实现MPI_THREAD_SERIALIZED所要求的MPI调用的序列化)一旦探测结果成功,则为MPI_Iprobe

// 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) { ... }表示法替换为编程环境提供的原语。

答案 1 :(得分:0)

如果我理解正确,那不是你收到信息的方式,而是你如何发送信息。如下所示MPI_Send函数有destination参数,该参数定义了此消息将被发送到哪个线程。

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

因此,如果您想让某些线程收到某些消息,则必须将此消息仅发送到该线程。