【发布时间】:2014-04-06 03:31:07
【问题描述】:
在related question 中,我了解到执行request = Isend(...); Recv(...); request.Wait(); 是不保证工作,因为Isend 在request.Wait() 之前可能不会做任何事情,因此在Recv(...) 处死锁(见原文详情提问)。
但是如果Isend() / Wait() 在Recv 之外的另一个线程上执行呢?我现在对标准的安全保证不直接感兴趣。这是因为标准只断言线程安全,如果适当的Init_thread 方法被调用并返回正确的级别。对于我的 openMPI 配置,情况并非如此。但是,我看不出一个实现实际上将调用限制为仅来自调用 Init_thread 的线程的原因(需要对线程 ID 进行实际比较)。我的理由是:如果我序列化所有发送和所有接收,mpi 永远不会注意到我正在使用多个线程。
所以我的简化代码是这样的:
#include <cassert>
#include <thread>
#include "mpi.h"
void send(int rank, int& item)
{
MPI::Request request = MPI::COMM_WORLD.Isend(&item, sizeof(int), MPI::BYTE, rank, 0);
request.Wait();
}
void recv(int rank, int& item)
{
MPI::COMM_WORLD.Recv(&item, sizeof(int), MPI::BYTE, rank, 0);
}
int main()
{
MPI::Init();
int ns[] = {-1, -1};
int rank = MPI::COMM_WORLD.Get_rank();
ns[rank] = rank;
auto t_0 = std::thread(send, 1 - rank, std::ref(ns[rank])); // send rank to partner (i.e. 1 - rank)
auto t_1 = std::thread(recv, 1 - rank, std::ref(ns[1 - rank])); // receive partner rank from partner
t_0.join();
t_1.join();
assert( ns[0] == 0 );
assert( ns[1] == 1 );
MPI::Finalize();
}
代码解释:每个处理器上执行两个线程。一个尝试向合作伙伴Isend一些数据并等待直到完成,另一个从合作伙伴接收一些数据。
问题:我可以安全地假设大多数 MPI 实现不会因这段代码而窒息吗?
(免责声明:这段代码并非设计为异常安全或特别漂亮。仅用于演示目的)
【问题讨论】:
-
您在相关问题中学到的内容是错误的。
-
@HristoIliev 感谢您在那里发布答案:) 这是个好消息(嗯,部分。这意味着其他地方有一个错误-.-),因为我不必抛出完全离开我的概念
标签: c++ thread-safety mpi communication openmpi