混合 C++11 原子和 OpenMP
Mixing C++11 atomics and OpenMP
OpenMP 有自己的原子访问支持,但是,首选 C++11 原子至少有两个原因:它们明显更灵活,并且它们是标准的一部分。另一方面,OpenMP比C++11线程库更强大。
标准在两个不同的章节中指定了原子操作库和线程支持库。这让我相信用于原子访问的组件与所使用的线程库有点正交。我真的可以结合 C++11 原子和 OpenMP 吗?
Stack Overflow 上有一个非常similar question;然而,三年来基本上没有答案,因为它的答案没有回答实际问题。
更新:
OpenMP 5.0 定义了与 C++11 及更进一步的交互。其中,它表示使用以下功能可能会导致未指定的行为:
- 数据依赖排序:原子和内存模型
- 标准库的补充
- C++11 库
很明显,混合使用 C++11 原子和 OpenMP 5.0 将导致未指定的行为。至少标准本身承诺 "future versions of the OpenMP specification are expected to address [these] features".
旧讨论:
有趣的是,OpenMP 4.5 标准 (2.13.6) 对 C++11 原子的引用相当模糊,或者更具体 std::memory_order
:
The intent is that, when the analogous operation exists in C++11 or
C11, a sequentially consistent atomic construct has the same semantics
as a memory_order_seq_cst atomic operation in C++11/C11. Similarly, a
non-sequentially consistent atomic construct has the same semantics as
a memory_order_relaxed atomic operation in C++11/C11.
不幸的是,这只是一个音符,没有任何东西可以定义他们一起玩得很好。特别是,即使是最新的 OpenMP 5.0 预览版仍然将 C++98 作为 C++ 的唯一规范参考。所以 从技术上讲,OpenMP 本身甚至不支持 C++11。
除此之外,它在实践中可能大部分时间都有效。我同意,与 C++11 线程相比,如果与 OpenMP 一起使用,使用 std::atomic
出现问题的可能性较小。但如果有任何麻烦,它可能不会那么明显。最坏的情况是原子不能以原子方式运行,尽管我很难想象可能发生这种情况的现实场景。归根结底,这可能不值得,最安全的做法是坚持使用纯 OpenMP 或纯 C++11 thread/atomics.
也许 Hristo 对此有话要说,同时查看 this answer 以获得更一般的讨论。虽然有点过时,恐怕它仍然有效。
目前 OpenMP 4.5 未指定。实际上,您可以在大多数编译器中对 OpenMP 线程使用 C++11 原子操作,但没有正式保证它会起作用。
由于未指定的行为,GCC 直到最近才支持 C11 原子(其语义与 C++11 原子几乎相同)和 OpenMP 线程。有关详细信息,请参阅 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65467。
OpenMP 5.0 试图解决这个问题。规范语言参考已更新为 C11 和 C++11。但是,这些原子和内存模型是 "not supported",这意味着 implementation-defined。我希望 OpenMP 5.0 说得更多,但定义 OpenMP 和 ISO 语言原子的交互非常困难。
OpenMP 有自己的原子访问支持,但是,首选 C++11 原子至少有两个原因:它们明显更灵活,并且它们是标准的一部分。另一方面,OpenMP比C++11线程库更强大。
标准在两个不同的章节中指定了原子操作库和线程支持库。这让我相信用于原子访问的组件与所使用的线程库有点正交。我真的可以结合 C++11 原子和 OpenMP 吗?
Stack Overflow 上有一个非常similar question;然而,三年来基本上没有答案,因为它的答案没有回答实际问题。
更新:
OpenMP 5.0 定义了与 C++11 及更进一步的交互。其中,它表示使用以下功能可能会导致未指定的行为:
- 数据依赖排序:原子和内存模型
- 标准库的补充
- C++11 库
很明显,混合使用 C++11 原子和 OpenMP 5.0 将导致未指定的行为。至少标准本身承诺 "future versions of the OpenMP specification are expected to address [these] features".
旧讨论:
有趣的是,OpenMP 4.5 标准 (2.13.6) 对 C++11 原子的引用相当模糊,或者更具体 std::memory_order
:
The intent is that, when the analogous operation exists in C++11 or C11, a sequentially consistent atomic construct has the same semantics as a memory_order_seq_cst atomic operation in C++11/C11. Similarly, a non-sequentially consistent atomic construct has the same semantics as a memory_order_relaxed atomic operation in C++11/C11.
不幸的是,这只是一个音符,没有任何东西可以定义他们一起玩得很好。特别是,即使是最新的 OpenMP 5.0 预览版仍然将 C++98 作为 C++ 的唯一规范参考。所以 从技术上讲,OpenMP 本身甚至不支持 C++11。
除此之外,它在实践中可能大部分时间都有效。我同意,与 C++11 线程相比,如果与 OpenMP 一起使用,使用 std::atomic
出现问题的可能性较小。但如果有任何麻烦,它可能不会那么明显。最坏的情况是原子不能以原子方式运行,尽管我很难想象可能发生这种情况的现实场景。归根结底,这可能不值得,最安全的做法是坚持使用纯 OpenMP 或纯 C++11 thread/atomics.
也许 Hristo 对此有话要说,同时查看 this answer 以获得更一般的讨论。虽然有点过时,恐怕它仍然有效。
目前 OpenMP 4.5 未指定。实际上,您可以在大多数编译器中对 OpenMP 线程使用 C++11 原子操作,但没有正式保证它会起作用。
由于未指定的行为,GCC 直到最近才支持 C11 原子(其语义与 C++11 原子几乎相同)和 OpenMP 线程。有关详细信息,请参阅 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65467。
OpenMP 5.0 试图解决这个问题。规范语言参考已更新为 C11 和 C++11。但是,这些原子和内存模型是 "not supported",这意味着 implementation-defined。我希望 OpenMP 5.0 说得更多,但定义 OpenMP 和 ISO 语言原子的交互非常困难。