注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

widebright的个人空间

// 编程和生活

 
 
 

日志

 
 

C++0x 内存模型和原子操作 (std:::atomic memory order等相关资料)  

2012-06-05 15:22:38|  分类: 程序设计 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

并行编程的趋势不可阻挡啊,新的c++标准也加入了很多支持。内存模型和 std::atomic 的引入很值得学习吧,看facebook的开源c++库都用了很多c++ 11的特性了。 std::atomic 这些。

网上看到的最详细清楚的解释是,
C++ Concurrency in Action.pdf  一书的第五章
5 The C++ Memory Model and Operations on Atomic Types
对理解 c++ atomic 的memory order很有用处:

这个网页其实也是摘录的书的内容来的,
Memory Ordering for Atomic Operations in C++0x
http://www.developerfusion.com/article/138018/memory-ordering-for-atomic-operations-in

-c0x/

详细解析了 std::atomic 的不同存储模型 ,不同的值与memory order的关系:

有了linux内核的里面内核屏障的概念的话,像下面这样里面比较容易吧。

typedef enum memory_order {

    memory_order_relaxed,   \\ 不指定内存屏障,所以内存操作执行时可能是乱序的。

    memory_order_acquire,   \\ 按照我理解就是插入一个 内存读屏障,保证之前的读操作先一步完成。清空自己cpu上"invalidate queues"  。

    memory_order_release,    \\ 按照我理解就是插入一个 内存写屏障,保证之前的写操作的顺序一定 。清空自己cpu上 的 “ store buffer"


在这之前完成

    memory_order_consume  类似memory_order_acquire,但只对依赖的指定数据起作用。

    memory_order_acq_rel,    \\ 同时插入读写两个屏障。  清空自己cpu上 的 “ store buffer" 和 "invalidate queues"  。

    memory_order_seq_cst    \\\默认的顺序模型。根据  http://en.cppreference.com/w/cpp/atomic/memory_order 这里的说明 (Total sequential ordering requires a full memory fence CPU instruction on all multi-core systems. This may become a performance bottleneck since it forces all memory accesses to propagate to every thread.)  这个会清空所有cpu上的读写同步消息队列 “ store buffer" 和 "invalidate queues"   (参考 http://gmd20.blog.163.com/blog/static/168439232013025104347654/ ) 。  memory_order_acq_rel 应该是只清空自己cpu上 的 “ store buffer" 和 "invalidate queues"  。

        这个看上去和x86的lock指令前缀锁总线不太一样。不知道具体怎么实现的。

 

} memory_order;


书上的一个简单的例子。
-----------------------------------------------
#include <atomic>
#include <thread>
#include <assert.h>
 
std::atomic<bool> x,y;
std::atomic<int> z;
 
void write_x_then_y()
{
    x.store(true,std::memory_order_relaxed);             #1
    y.store(true,std::memory_order_release);             #2   //保证 第#1句的x写入在y的写入之前
}
 
void read_y_then_x()
{
    while(!y.load(std::memory_order_acquire));           #3     //保证 y的读取在 第#4句x的读取之前。所以  如果y看到修改后的值,肯定 第#4句看到的也是x的新的值了。
    if(x.load(std::memory_order_relaxed))                #4
        ++z;
}
 
int main()
{
    x=false;
    y=false;
    z=0;
    std::thread a(write_x_then_y);
    std::thread b(read_y_then_x);
    a.join();
    b.join();
    assert(z.load()!=0);                                 #5    //这个肯定通过的了。
}
-----------------------------------------------------------


也说道了内存屏障了
memory fences/barriers
c++ 里面除了上面那些为atomic类型指定明确的存储模型之外,也可以插入 指定的“内存读写屏障 

”的。


书中的其他章节也挺不粗哦的,
7
Designing Data Structures for
Concurrency II: Lock-free
Concurrent Data Structures


相面这个应该是c++的规范文档,解释了为什么要把c++的内存模型定义成这样子。
C++ Atomic Types and Operations
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2427.html#DiscussOrder
Memory Model Rationales
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2176.html


想std:atomic 等特性,应该在行的gcc 和 vc11 里面都有支持了,
C++11 Features in Visual C++ 11
http://blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx
Status of Experimental C++0x Support in GCC 4.6
http://gcc.gnu.org/gcc-4.6/cxx0x_status.html

像facebook的开源c++库好像这个std::atomic用的很多了,用来实现spinlock 。
可以去参考一下 https://github.com/facebook/folly/tree/master/folly



补充:
The Purpose of memory_order_consume in C++11
http://preshing.com/20140709/the-purpose-of-memory_order_consume-in-cpp11/

c++ 牛人Jeff Preshing (好像是个游戏大公司的架构师)写了一篇文章详细解释了 memory_order_consume  的原理。
图示什么比较清楚,可以去看一下原文。
 memory_order_consume  可以达到和 memory_order_acquire 同样 目的, 但memory_order_consume 依赖于 硬件的 “数据依赖(Data Dependency Ordering)”保证来实现的(硬件自动保证相互依赖的读写指令的顺序), memory_order_acquire 是直接插入 内存屏障指令保证读取顺序。 在某些平台比如ARM POWERPC那些读取顺序会乱序的平台上面,内存读取屏障是会导致严重的性能损失的。x86这种读取不会乱序的则这两种memory_order_consume和memory_order_acquire都不需要插入内存屏障,所以没没什么影响。
但现在编译器支持都做的不好,估计是通过“数据依赖”保证比较难以实现,当前的实现memory_order_consume都退还成memory_order_acquire了。
文章提到linux 内核 https://www.kernel.org/doc/Documentation/RCU/rcu_dereference.txt  里面的RCU也是通过数据依赖来保证顺序的。



  评论这张
 
阅读(1407)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017