std::atomic能否安全地与OpenMP一起使用?

12

我目前正在尝试学习如何使用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;
  }

谢谢!

编辑:我知道处理这个的最简单方式是使用一个数组,但我问这个问题是因为我很好奇。


8
std::atomic是C++11标准多线程框架提供的一种工具。如果你将std::atomic与像OpenMP这样提供自己实现此类功能的外部库结合使用,可能会遇到问题。 - Marc Claesen
6
实际上,原子库在标准中的章节与线程库不同。此外,在原子章节中我没有发现任何说明表明该库仅适用于std::thread。 - gTcV
我同意 @gTcV 的观点 - 原子类型是使用 C++ 内存模型而非线程实现。例如,在 omp 段落中使用智能指针会导致引用计数器的竞争条件。 - Victor Proon
1
GCC曾经在你想要在OpenMP并行区域内使用C11或C++11原子时产生错误。如果OpenMP原子没有比使用C++11更复杂,我会坚持使用前者,因为你只依赖于OpenMP标准(你可以使用不支持C++11的编译器)。 - Jorge Bellon
3
可能是 Mixing C++11 atomics and OpenMP 的重复问题。 - Zulan
2个回答

3
官方上来说不行,但实际上可能可以。在《OpenMP 5.0规范》的第32页的第1.7节中说到:
“虽然未来版本的OpenMP规范有望解决以下功能,但目前使用这些功能可能会导致未指定的行为。”
  • 并发性

  • 标准库的增加

  • C++11库

然而,取决于您所使用的OpenMP运行时的实现,这可能是可以的。事实上,LLVM OpenMP运行时甚至使用std::atomic来实现一些OpenMP规范。

然而,最安全的选择是仅使用OpenMP提供的内容。您可以使用std::atomic实现的任何操作,也应该能够仅使用OpenMP实现。


2
这个问题已经在OpenMP 5.1中得到了修复:https://www.openmp.org/wp-content/uploads/OpenMP-API-Specification-5-1.pdf - kc9jud
你可以使用std::atomic来实现的任何功能,也可以通过OpenMP来实现。std::atomic用于无锁编程,例如在不使用互斥锁和临界区的情况下更新共享计数器。那么OpenMP如何实现这个功能呢? - undefined
https://www.openmp.org/spec-html/5.0/openmpsu95.html - undefined

-2

由于原子操作会减慢并行执行速度,而且不易扩展,因此最好避免使用。

pragma omp parallel for reduction(+:result)
for(...)
{
  double tmp=0;
  //some stuff;
  result+=tmp;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接