作为我上一个问题的后续,atomic<T>
该类使用参数指定大多数操作memory_order
。与栅栏相反,此内存顺序仅影响其操作的原子。大概通过使用几个这样的原子,您可以构建一个并发算法,其中其他内存的顺序并不重要。
所以我有两个问题:
- 有人可以指出一个算法/情况的示例,该算法/情况将受益于单个原子变量的排序并且不需要围栏?
- 哪些现代处理器支持这种行为?也就是说,编译器不会只是将特定顺序转换为正常的栅栏。
作为我上一个问题的后续,atomic<T>
该类使用参数指定大多数操作memory_order
。与栅栏相反,此内存顺序仅影响其操作的原子。大概通过使用几个这样的原子,您可以构建一个并发算法,其中其他内存的顺序并不重要。
所以我有两个问题:
std::atomic<T>
变量操作的内存排序参数不会影响该操作本身的排序,它会影响操作与其他操作创建的排序关系。
例如a.store(std::memory_order_release)
,它本身并没有告诉你关于a
其他任何事情的操作是如何排序的,而是与另一个线程的调用配对a.load(std::memory_order_acquire)
,然后对其他操作进行排序——所有对其他变量(包括非原子变量)的写入都已完成如果加载读取存储的值,则执行存储a
的线程对执行加载的线程可见。
在现代处理器上,一些关于操作的内存排序是无操作的。例如在 x86 上memory_order_acquire
,memory_order_consume
和memory_order_release
隐含在加载和存储指令中,不需要单独的栅栏。在这些情况下,排序只会影响编译器可以执行的指令重新排序。
澄清:指令中的隐式栅栏可能意味着如果所有内存排序约束都附加到原子变量上的单个操作,编译器不需要发出任何显式栅栏指令。如果您memory_order_relaxed
对所有内容都使用并添加显式栅栏,那么编译器很可能必须将这些栅栏作为指令显式发出。
例如,在 x86 上,该XCHG
指令带有一个隐含的memory_order_seq_cst
栅栏。因此,在 x86 上为以下两个交换操作生成的代码之间没有区别 --- 它们都映射到一条XCHG
指令:
std::atomic<int> ai;
ai.exchange(3,std::memory_order_relaxed);
ai.exchange(3,std::memory_order_seq_cst);
但是,我还不知道有任何编译器摆脱了以下代码中的显式围栏指令:
std::atomic_thread_fence(std::memory_order_seq_cst);
ai.exchange(3,std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_seq_cst);
我希望编译器最终会处理这种优化,但在其他类似的情况下,隐式围栏将允许更好的优化。
此外,std::memory_order_consume
只能应用于对变量的直接操作。