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<int> 索引对大型数组进行异步并行化操作有多安全