首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MPI异步发送的安全保障

MPI异步发送的安全保障
EN

Stack Overflow用户
提问于 2014-02-27 20:11:51
回答 2查看 759关注 0票数 0

在我的应用程序中,我使用MPI以主从方式分发作业。一项工作交给奴隶,然后收集结果。在这个程序的多线程版本中,当所有处理器同时尝试Send (阻塞)时,可能会出现死锁,因为没有匹配的Recv。我想出了一个似乎可行的解决方案,但我想得到保证(除了再测试一万次)。

我的程序的安全性是肯定的,如果这个小代码被保证--提供一个一致的实现。(显然,这只适用于两个处理器,而不是针对更多处理器):

代码语言:javascript
复制
#include <cassert>
#include "mpi.h"

int main()
{
   MPI::Init();
   int ns[] = {-1, -1};
   int rank = MPI::COMM_WORLD.Get_rank();
   ns[rank] = rank;
   MPI::Request request = MPI::COMM_WORLD.Isend(&rank, sizeof(int), MPI::BYTE, 1 - rank, 0);
   MPI::COMM_WORLD.Recv(&ns[1 - rank], sizeof(int), MPI::BYTE, 1 - rank, 0);
   request.Wait();
   assert( ns[0] == 0 );
   assert( ns[1] == 1 );
   MPI::Finalize();
}

所以我的问题是:IsendRecv交织在一起,直到我在由Isend返回的Request上调用Wait之前,在MPI中是一个定义良好的安全的东西吗?

(免责声明:这段代码不是设计为异常安全或特别漂亮。只供演示之用)

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-03-04 15:38:31

你的密码非常安全。这是由MPI标准§3.7.4 -非阻塞通信的语义所定义的非阻塞操作的语义所保证的:

完成接收的对MPI_WAIT的调用,如果已启动匹配的发送,则最终将终止并返回,除非另一个接收满足该发送。特别是,如果匹配的发送是非阻塞的,那么即使发送方没有执行任何调用来完成发送,接收也应该完成。类似地,如果已启动匹配的接收,则对完成发送的MPI_WAIT的调用最终将返回,除非接收被另一个发送所满足,而且即使没有执行调用来完成接收。

该上下文中的阻塞操作相当于启动非阻塞操作,紧接着是等待操作。

如果标准的话不够让人放心,那么Open中MPI_SENDRECV实现中的这个代码部分可能会有所帮助:

代码语言:javascript
复制
if (source != MPI_PROC_NULL) { /* post recv */
    rc = MCA_PML_CALL(irecv(recvbuf, recvcount, recvtype,
                            source, recvtag, comm, &req));
    OMPI_ERRHANDLER_CHECK(rc, comm, rc, FUNC_NAME);
}

if (dest != MPI_PROC_NULL) { /* send */
    rc = MCA_PML_CALL(send(sendbuf, sendcount, sendtype, dest,
                           sendtag, MCA_PML_BASE_SEND_STANDARD, comm));
    OMPI_ERRHANDLER_CHECK(rc, comm, rc, FUNC_NAME);
}

if (source != MPI_PROC_NULL) { /* wait for recv */
    rc = ompi_request_wait(&req, status);
} else {
    if (MPI_STATUS_IGNORE != status) {
        *status = ompi_request_empty.req_status;
    }
    rc = MPI_SUCCESS;
}

如果使用Irecv / Send / Wait(receive)Isend / Recv / Wait(send)并不重要--当涉及到可能的死锁时,两者都是同样安全的。当然,如果交错操作不正确匹配,死锁可能(而且会)发生。

使您的代码变得不一致的唯一原因是它使用了C++ MPI绑定。这些建议在MPI-2.2中被否决,在MPI-3.0中被删除.您应该使用C来代替。

票数 1
EN

Stack Overflow用户

发布于 2014-02-27 21:51:12

此代码不能保证工作正常。在调用相应的Isend函数之前,MPI实现可以不执行任何与您的Wait相关的操作。

更好的选择是使您的SendRecv函数非阻塞。您可以使用IsendIrecv,而不是使用Wait,而是使用WaitallWaitall函数接受一个MPI请求数组,并同时等待所有请求(同时在每个请求上都取得进展)。

所以你的程序会是这样的:

代码语言:javascript
复制
#include <cassert>
#include "mpi.h"

int main()
{
   MPI::Init();
   int ns[] = {-1, -1};
   int rank = MPI::COMM_WORLD.Get_rank();
   MPI::Request requests[2];
   ns[rank] = rank;
   requests[0] = MPI::COMM_WORLD.Isend(&rank, sizeof(int), MPI::BYTE, 1 - rank, 0);
   requests[1] = MPI::COMM_WORLD.Irecv(&ns[1 - rank], sizeof(int), MPI::BYTE, 1 - rank, 0);
   MPI::Request::Waitall(2, requests)
   assert( ns[0] == 0 );
   assert( ns[1] == 1 );
   MPI::Finalize();
}
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22079306

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档