2011-04-06 66 views
6

作为我以前的question的后续,atomic<T>类用memory_order参数指定了大多数操作。与篱笆相比,这种记忆顺序仅影响其操作的原子。大概通过使用几个这样的原子,你可以建立一个并行算法,其他内存的排序是不重要的。C++ 0X memory_order无栅栏,应用程序,支持的芯片

所以我有两个问题:

  1. 有人可以点我的算法/局面,将有利于从各个原子变量的排序和需要围栏的例子吗?
  2. 哪些现代处理器支持这种类型的行为?也就是说,编译器不会将特定顺序转换为常规围栏。

回答

4

内存排序在操作上std::atomic<T>变量参数不影响操作本身的排序,它会影响操作与其他操作产生的排序关系。

例如a.store(std::memory_order_release)自身不能告诉你关于a操作如何相对于别的排序,但从另一个线程a.load(std::memory_order_acquire)通话配对,这则命令其他操作---所有写入到其他变量(包括非原子的)通过执行加载的线程可以看到存储到a的线程完成,如果该加载读取存储的值。

在现代处理器上,操作上的一些内存排序是空操作。例如在x86上,memory_order_acquire,memory_order_consumememory_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可以只有适用于直接操作变量。

+0

是的,我明白这一点,这就是我的意思*这种记忆顺序只影响其操作的原子*。这两个问题依然存在。 – 2011-04-06 08:02:53

+0

如果通过指定“原子”上的内存顺序来保证*关系与*关系的保证,并且保护范围只能保证与“原子”操作一起工作,那么为什么标准中甚至存在栅栏。只需在变量上使用内存顺序就不需要任何围栏。而且由于你没有被允许在没有原子的情况下使用栅栏,所以我看不到你实际上想要栅栏的情况。 – 2011-04-07 04:35:33

+1

有条件的围栏是您希望使用显式围栏的一种情况。例如 'std :: atomic p; (p.load(std :: memory_order_relaxed)){ std :: thread_fence(std :: memory_order_acquire); do_something_with(* p); }' 或旋等待循环后:(!p.load(标准:: memory_order_relaxed)) '而{ 的std :: this_thread ::收率(); } std :: thread_fence(std :: memory_order_acquire);' – 2011-04-07 06:43:17