【问题标题】:Is it safe to call MPI_Init from different thread?从不同的线程调用 MPI_Init 是否安全?
【发布时间】:2018-03-12 12:04:29
【问题描述】:

std::thread 调用MPI_Init 是否安全?

int main(int argc, char** argv) {

    std::thread mpi_thread([...](){
        MPI_Init(...);

       // All MPI calls are done by this thread.

        MPI_Finalize();
    });

    // The main thread is doing different stuff

    mpi_thread.join();
    return 0;
}

【问题讨论】:

  • 我看不出有什么问题,但我想知道这样做的目的是什么。
  • 您可能还想使用Boost.MPI 以获得更好的界面。
  • 我暂时是这样,但Boost.MPI 有自己的一系列问题。很多时候,您必须回退到 MPI 文档才能猜测发生了什么。

标签: c++ mpi


【解决方案1】:

好的,这里有两个问题

1) 问题中的代码是否“安全”

是的,这里显示的代码是 100% 安全的,因为 MPI 计算发生在单个线程上。如果某些事情“出错”,我们需要一个可重现的示例,其中包括编译器和有关集群的一些信息。有可能是由于供应商特定的配置问题,很多年前供应商会“祝福” MPI 的主线程。

2) MPI 线程安全吗? AKA 你可以在第二个线程上调用MPI_RECV 吗?

这是这里讨论的更难的问题:thread safety of MPI send using threads created with std::async

【讨论】:

  • 非常感谢。我知道,MPI 通常不是线程安全的(必须努力学习)。
  • 我什至会说您答案的第 (2) 部分是不明智的。这种情况或多或少会导致死锁。
  • @HenriMenke 哪个部分?我不建议组合线程库(又名使用 pthreads/std:: 用于节点本地通信但节点之间的 MPI),如果不仅仅是为了代码复杂性。尽管一些资源过多的研究小组会这样做。
【解决方案2】:

MPI standard 有一个关于MPI 和线程 的部分。一个重要的部分是:

初始化和完成 对MPI_FINALIZE 的调用应该发生在初始化 MPI 的同一线程上。我们将此线程称为主线程。呼叫应仅在之后发生 所有进程线程都已完成其 MPI 调用,并且没有挂起的通信或 I/O 操作。

您的代码确实满足此要求。

MPI 知道多个级别的线程支持。您的代码要求:

MPI_THREAD_FUNNELED 进程可能是多线程的,但应用程序必须确保只有主线程进行 MPI 调用。

为了更好地衡量,您应该调用以下而不是MPI_Init

int provided;
MPI_Init_thread(NULL, NULL, MPI_THREAD_FUNNELED, &provided);
if (provided < MPI_THREAD_FUNNELED)
    MPI_Abort(MPI_COMM_WORLD, -1);

不符合线程要求的 MPI 库必须返回 provided == MPI_THREAD_SINGLE,表明您将无法在代码中正确使用此实现。

在实践中,您应该可以使用常见的实现。有关不同级别的线程支持的更多信息,请参阅 MPI 标准中的 12.4.3。随着更高级别的线程支持,您的里程可能会根据您选择的实现而有所不同。

【讨论】:

  • 非常感谢。参考标准的细节非常详细。
猜你喜欢
  • 1970-01-01
  • 2021-09-04
  • 2019-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-15
  • 2011-09-16
相关资源
最近更新 更多