std::atomic 可以安全地与 OpenMP 一起使用吗

Posted

技术标签:

【中文标题】std::atomic 可以安全地与 OpenMP 一起使用吗【英文标题】:Can std::atomic be safely used with OpenMP 【发布时间】:2014-02-28 12:25:13 【问题描述】:

我目前正在尝试学习如何使用 OpenMP,但我有一个问题。 这样做是否安全:

  std::atomic<double> result;
  #pragma omp parallel for
  for(...)
  
  result+= //some stuff;
  

或者我应该使用:

  double result;
  #pragma omp parallel for
  for(...)
  
    double tmp=0;
    //some stuff;
    #pragma omp atomic
    result+=tmp;
  

谢谢!

编辑:我知道最简单的处理方法是使用数组,但我问是因为我很好奇

【问题讨论】:

std::atomic 是 C++11 标准的多线程框架提供的工具。如果您将 std::atomic 与 OpenMP 等外部库结合使用,这些库提供自己的此类功能实现,您可能会遇到问题。 实际上,原子库与线程库在标准的不同章节中指定。另外,我在 atomic 章节中没有发现任何说明该库仅用于 std::thread 的注释。 我同意@gTcV - 原子类型使用 c++ 内存模型运行,而不是线程实现。例如,这将利用 omp 部分中的智能指针导致引用计数器的竞争条件 GCC 用于在您想要在 OpenMP 并行区域内使用 C11 或 C++11 原子的情况下生成错误。如果 OpenMP 原子不会引入比使用 C++11 的任何额外的复杂性,我会坚持使用前者,因为您将只依赖于 OpenMP 标准(您可以使用不支持 C++11 的编译器)。 Mixing C++11 atomics and OpenMP的可能重复 【参考方案1】:

正式来说,没有。在实践中,可能。

OpenMP 5.0 Specification 的第 1.7 页第 32 页说:

虽然 OpenMP 规范的未来版本预计将解决以下功能,但目前使用它们可能会导致未指定的行为。

并发

对标准库的补充

C++11 库

但是,根据您使用的 OpenMP 运行时的实现,可能没问题。事实上,LLVM OpenMP 运行时甚至使用std::atomic 来实现一些 OpenMP 规范。

不过,最安全的选择是坚持只使用 OpenMP 提供的功能。您可以使用std::atomic 执行的任何操作,您也应该能够仅使用 OpenMP 来实现。

【讨论】:

这已在 OpenMP 5.1 中修复:openmp.org/wp-content/uploads/OpenMP-API-Specification-5-1.pdf【参考方案2】:

由于原子会减慢并行执行速度并且不能很好地扩展,所以最好这样做

pragma omp parallel for reduction(+:result)
for(...)

  double tmp=0;
  //some stuff;
  result+=tmp;

【讨论】:

以上是关于std::atomic 可以安全地与 OpenMP 一起使用吗的主要内容,如果未能解决你的问题,请参考以下文章

我可以在 C++ 中仅使用 std::atomic 而不使用 std::mutex 安全地共享一个变量吗?

我可以制作一个线程安全的 std::atomic<vector<int>> 吗?

std::atomic 与另一个字符联合

使用 std::atomic<int> 索引对大型数组进行异步并行化操作有多安全

当类型不是 Integral 时,如何使用 std::atomic 执行基本操作?

使用原子的线程安全单例