我正在开发一个使用MPI例程和多个线程来发送和接收消息的项目。我希望每个接收线程专注于不同的传入消息,而不是让两个或更多尝试接收相同的消息。有没有办法实现这个目标?
我不知道这是否有帮助,但我目前正在使用Iprobe()来检查传入的消息,使用Test()检查Irecv()以检查线程是否已收到整条消息。
答案 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_Improbe
在flag
中返回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)
因此,如果您想让某些线程收到某些消息,则必须将此消息仅发送到该线程。