2012-11-20 29 views
2

我有一个内存变量在线程A中更新并在其他线程中读取。读者只关心该值是否为非零。我保证一旦数值递增,它就不会回到零。 如下优化是否有意义?换句话说,在读者方面,一旦我的条件得到满足,我就不需要“围栏”。C++原子加载排序效率

std::atomic<int> counter; 

writer: 
increment() 
{ 
    counter.store(counter+1, std:memory_order_release) 
} 

reader: 
iszero() 
{ 
    if (counter.load(std::memory_order_relaxed) > 0) return false; 
    // memory fence only if condition not yet reached 
    return (counter.load(std::memory_order_acquire) == 0); 
} 
+1

计数器可能会回到零。 –

+0

在reader :: iszero()中有一个线程局部布尔值并将其设置为true,以便您第一次从计数器获得非零值。如果是这样,立即返回false。只有当它仍然是错误的,请检查柜台。 –

+0

读者多久访问一次?这似乎是不成熟的优化。 –

回答

2

首先,如果你不使用默认的(顺序一致)原子能,测量你的应用程序的性能真正尝试,异形的,并显示他们观察到导致性能问题,我建议义无反顾现在。

但是,如果你实在需要开始推理轻松原子能...


这是不能保证你所期望的,但它几乎肯定会在x86工作。

我猜你正在用这个来防范其他一些非原子数据的发布。

在这种情况下,你需要保证如果您在读取器线程读取一个非零值,然后各种其他副作用,以非原子存储单元(即初始化你的数据发布)在商店之前在作者线程中发布的内容将对读者线程可见。

读取非零与std::memory_order_relaxed同步std::memory_order_release存储,所以你的代码上面没有这个保证。

为了得到我所描述的行为,您需要使用std::memory_order_acquire。如果你在x86上,那么获取不会产生任何内存围栏指令,所以它的性能与memory_order_relaxed不同的唯一方法是通过防止一些编译器优化。

+0

首先,就我而言,只有当我关心原子位置的新的非零值时,我才关心非atmoic位置。我检查了x86指令 - 你说得对,在获取和放宽之间似乎没有区别 - 都使用mov。我只需要保证所有商店都是按顺序看到的。我希望我可以通过发布获得更轻的指令集,但似乎并非如此。 – excalibur