C++ 中的内存栅栏/屏障:boost 或其他库有它们吗?

发布于 2024-09-26 02:26:27 字数 186 浏览 9 评论 0原文

这些天我正在阅读有关内存栅栏和屏障的内容,作为同步多线程代码和避免代码重新排序的一种方法。

我通常在 Linux 操作系统下使用 C++ 进行开发,并且大量使用 boost 库,但我找不到任何与之相关的类。你知道boost中是否存在栅栏的内存屏障或者是否有办法实现相同的概念?如果没有的话我可以去哪个好的图书馆看看?

I am reading these days about memory fences and barriers as a way to synchronize multithreaded code and avoid code reordering.

I usually develop in C++ under Linux OS and I use boost libs massively but I am not able to find any class related to it. Do you know if memory barrier of fences are present in boost or if there is a way to achieve the same concept? If not what good library can I have a look to?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

清眉祭 2024-10-03 02:26:27

boost 中还没有低级内存屏障,但有一个提议的 boost.atomic 库提供了它们。

编译器提供自己的内部函数或库函数,例如用于 Visual Studio 的 gcc __sync_synchronize() 或 _mm_mfence()

C++0x 库提供原子操作,包括内存栅栏,其形式为 <代码>std::atomic_thread_fence。尽管自 V4.4 以来 gcc 已经提供了各种形式的 C++0x 原子,但 V4.4 或 V4.5 都不包含这种形式的栅栏。我的(商业)just::thread 库提供了 C+ 的完整实现+0x 原子,包括 g++ 4.3 和 4.4 以及 Microsoft Visual Studio 2005、2008 和 2010 的栅栏。

There are no low-level memory barriers in boost yet, but there is a proposed boost.atomic library that provides them.

Compilers provide their own either as intrinsics or library functions, such as gcc's __sync_synchronize() or _mm_mfence() for Visual Studio.

The C++0x library provides atomic operations including memory fences in the form of std::atomic_thread_fence. Though gcc has supplied various forms of the C++0x atomics since V4.4, neither V4.4 or V4.5 include this form of fence. My (commercial) just::thread library provides a full implementation of C++0x atomics, including fences for g++ 4.3 and 4.4, and Microsoft Visual Studio 2005, 2008 and 2010.

长伴 2024-10-03 02:26:27

需要内存屏障的地方是在 SMP 环境中避免使用内核同步机制 - 通常是出于性能原因。

在任何内核同步操作(例如发信号量、锁定和解锁 mutices)和内容切换中都存在隐式内存屏障,以防止数据一致性危险。

我刚刚发现自己需要(适度)可移植的内存屏障实现(ARM 和 x86),并且还发现 linux 源代码树是最好的源代码。 Linux 具有 mb()rmb()wmb() 宏的 SMP 变体 - 在某些平台上会产生更具体的(和与非 SMP 变体相比,障碍可能成本更低。
这在 x86 上似乎不是问题,特别是 ARM,尽管两者的实现方式相同。

这是我从 Linux 头文件中抄写的内容(适用于 ARMv7 和非古老的 ​​x86/x64 处理器)。

#if defined(__i386__ ) || defined(__x64__)

#define smp_mb()    asm volatile("mfence":::"memory")
#define smp_rmb()   asm volatile("lfence":::"memory")
#define smp_wmb()   asm volatile("sfence" ::: "memory")
#endif

#if defined(__arm__)

#define dmb() __asm__ __volatile__ ("dmb" : : : "memory")

#define smp_mb()    dmb()
#define smp_rmb()   dmb()
#define smp_wmb()   dmb()
#endif

当然,涉足内存屏障会带来随之而来的风险,即生成的代码实际上无法测试,并且任何由此产生的错误都会晦涩难懂且难以重现竞争条件:/

顺便说一句,Linux 内核文档

The place where memory barriers are required is when avoiding using kernel synchronisation mechanisms in an SMP environment - usually for performance reasons.

There is an implicit memory barrier in any kernel synchronisation operation (e.g. signalling semaphores, locking and unlocking mutices) and content switching to guard against data coherence hazards.

I have just found myself needing (moderately) portable memory barrier implementations (ARM and x86), and also found the linux source tree to be the best source for this. Linux has SMP variants of the mb(), rmb() and wmb() macros - which on some platforms result in more specific (and possible less costly) barriers than the non-SMP variants.
This doesn't appear to be a concern on x86 and particularly ARM where though where both are implemented the same way.

This is what I've cribbed together from linux header files (suitable for ARMv7 and non-ancient x86/x64 processors)

#if defined(__i386__ ) || defined(__x64__)

#define smp_mb()    asm volatile("mfence":::"memory")
#define smp_rmb()   asm volatile("lfence":::"memory")
#define smp_wmb()   asm volatile("sfence" ::: "memory")
#endif

#if defined(__arm__)

#define dmb() __asm__ __volatile__ ("dmb" : : : "memory")

#define smp_mb()    dmb()
#define smp_rmb()   dmb()
#define smp_wmb()   dmb()
#endif

Naturally, dabbling with memory barriers has the attendant risk that the resulting code is practically impossible to test, and any resulting bugs will be obscure and difficult to reproduce race conditions :/

There is, incidentally, a very good description of memory barriers in the Linux kernel documentation.

稳稳的幸福 2024-10-03 02:26:27

有一个 boost::barrier 类/概念,但它的级别有点高。说到这里,为什么需要低等级的壁垒呢?同步原语应该足够了,不是吗?他们应该在必要时直接或间接通过其他较低级别的原语使用内存屏障。

如果您仍然认为需要低级实现,我知道没有实现屏障的类或库,但 Linux 内核中有一些特定于实现的代码。在 include/asm-{arch}/system.h< 中搜索 mb()rmb()wmb() /代码>。

There is a boost::barrier class/concept but it's a bit high level. Speaking of which, why do you need a low level barrier? Synchronization primitives should be enough, shouldn't they? And they should be using memory barriers where necessary, either directly or indirectly through other, lower level primitives.

If you still think you need a low-level implementation, I know of no classes or libraries that implement barriers, but there's some implementation-specific code in the Linux kernel. Search for mb(), rmb() or wmb() in include/asm-{arch}/system.h.

怎言笑 2024-10-03 02:26:27

现在,到 2019 年,C++11 栅栏应该可以在几乎所有 C++ 标准库的实现上使用。标头是

您可以通过调用 std::atomic_thread_fence 来发出栅栏。简而言之:

  • std::atomic_thread_fence(std::memory_order_release);保证没有任何存储操作被移动到调用之外。 (所有副作用将对其他线程可见。)
  • std::atomic_thread_fence(std::memory_order_acquire); 保证在调用之前不会移动任何加载操作。 (其他线程的所有副作用都将可见。)

文档中有更多详细信息< /a>.

Now, in 2019, the C++11 fences should be available on nearly every implementation of the C++ standard library. The header ist <atomic>.

You can issue a fence by calling std::atomic_thread_fence. In short:

  • std::atomic_thread_fence(std::memory_order_release); guarantees that no store operations are moved past the call. (All side effects will be made visible to other threads.)
  • std::atomic_thread_fence(std::memory_order_acquire); guarantees that no load operations are moved before the call. (All side effects of other threads will be made visible.)

There are more details in the documentation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文