Memory Ordering

 
  • Background 
    很久很久很久以前,CPU忠厚老实,一条一条指令的执行我们给它的程序,规规矩矩的进行计算和内存的存取。 
    很久很久以前, CPU学会了Out-Of-Order,CPU有了Cache,但一切都工作的很好,就像很久很久很久以前一样,而且工作效率得到了很大的提高。 
    很久以前,我们需要多个CPU一起工作,于是出现了传说中的SMP系统,每个CPU都有独立的Cache,都会乱序执行,会打乱内存存取顺序,于是事情变得复杂了……
  • Problem 
    由于每个CPU都有自己的Cache,内存读写不再一定需要真的作内存访问,而是直接从Cache里面操作,同时CPU可能会在合适的时候对于内存访问进行重新排序以提高效率,在只有一个CPU的时候,这很完美。 
    而当有多个CPU的时候——
    • 从Cache到内存的flush操作通常是被延迟的,所以就需要某种方法保证CPU A进行的内存写操作真的可以被CPU B读取到。
    • CPU可能会因为某些原因(比如某两个变量同在一个Cacheline中)而打乱
      • 实际内存写入顺序
      • 实际内存读取顺序

      所以就需要某种方法保证在需要的时候

      • 之前的读写操作已经完成
      • 未来的读写操作还没开始

    考虑一个例子: 
    Thread A: 
    while (flag == 0) 
            ; // do nothing 
    printf("%d\n", data); 
    Thread B: 
    data = 523; 
    flag = 1; 
    这里data代表了某种数据,它可以像这里一样是一个简单的整数,也可能是某种复杂的数据结构,总之,我们在Thread B中对data进行了写入,并利用flag变量表示data已经准备好了。 
    在Thread A中,一个忙等待直到发现data已经准备好了,然后开始使用data,这里是简单的把data打印出来。 
    现在考虑如果CPU发现对于data和flag的写入,如果按照先写入flag后写入data的方式进行,或者考虑由于Cache的flush操作的延迟,使得内存中变量的实际修改顺序是先flag后data,那么都将导致Thread A的结果不正确。事实上,由于内存读入操作同样是可能乱序进行的,Thread A甚至可能在读入flag进行判断之前就已经完成了对data的读入操作,这同样导致错误的结果。

  • Solution 
    在这个例子中,我们的需求是,Thread A中对于flag判断时,后面的任何读入操作都没有开始,Thread B中对于flag写入时,任何之前的写入操作都已经完成。 
    在Linux内核中,smp_rmb()、smp_wmb()、smp_mb()就是用来解决这类问题的,mb表示memory barrier。rmb表示读操作不可跨越(注意,不是人民币的意思:-P),也就是我们这个例子中的Thread A所需要的。wmb表示写操作不可跨越,也就是这里Thread B所需要的。mb集合了rmb和wmb的能力,读写操作都不可跨越。 
    在Qt中,其支持原子操作的类QAtomicInt支持四种类型的操作,Relaxed、Acquired、Release、Ordered,其中 Relaxed最为简单,就是不做特殊要求,由编译器和处理器对读写进行合适的排序。Acquired表示原子操作之后的内存操作不可被重排至原子操作之前。Release表示原子操作之前的内存操作不可被重排至原子操作之后。Ordered表示Acquired + Release。在前面的例子中,Thread A对于flag的读取操作需要Acquired版本,而Thread B对于flag的写入操作需要Release版本。 
    在实际实现中,不同体系结构的实现方法各不相同,很多RISC机器提供了专门的指令用于实现mb,而在x86上面,通常使用lock指令前缀加上一个空操作来实现,注意当然不能真的是nop指令,但是可以用来实现空操作的指令其实是很多的,比如Linux中采用的addl $0, 0(%esp)。Qt的不同类型原子操作由于本身就需要进行某种可被lock前缀修饰的操作,所以就不需要画蛇添足的再写一条空操作了,比如 testAndSetOrdered就可以直接使用lock cmpxchgl实现。

转贴自:http://etrnlog.appspot.com/2009/10/12/memory-ordering.html

Memory Ordering (注意Cache带来的副作用,每个CPU都有自己的Cache,内存读写不再一定需要真的作内存访问)的更多相关文章

  1. Multi-core compute cache coherency with a release consistency memory ordering model

    A method includes storing, with a first programmable processor, shared variable data to cache lines ...

  2. Memory Ordering in Modern Microprocessors

    Linux has supported a large number of SMP systems based on a variety of CPUs since the 2.0 kernel. L ...

  3. Satisfying memory ordering requirements between partial reads and non-snoop accesses

    A method and apparatus for preserving memory ordering in a cache coherent link based interconnect in ...

  4. memory ordering 内存排序

    Memory ordering - Wikipedia https://en.wikipedia.org/wiki/Memory_ordering https://zh.wikipedia.org/w ...

  5. C++ atomic 和 memory ordering 笔记

    如果不使用任何同步机制(例如 mutex 或 atomic),在多线程中读写同一个变量,那么,程序的结果是难以预料的.简单来说,编译器以及 CPU 的一些行为,会影响到程序的执行结果: 即使是简单的语 ...

  6. 在电脑主机(MainFrame)中只需要按下主机的开机按钮(on()),即可调用其它硬件设备和软件的启动方法,如内存(Memory)的自检(check())、CPU的运行(run())、硬盘(Hard

    欢迎大家加入我的社区:http://t.csdn.cn/Q52km 社区中不定时发红包 文章目录 1.UML类图 2.源码 3.优缺点 1.UML类图 2.源码 package com.zheng; ...

  7. QAtomicInt支持四种类型的操作,Relaxed、Acquired、Release、Ordered

    Memory Ordering   Background 很久很久很久以前,CPU忠厚老实,一条一条指令的执行我们给它的程序,规规矩矩的进行计算和内存的存取. 很久很久以前, CPU学会了Out-Of ...

  8. 操作系统之cache、伙伴系统、内存碎片、段式页式存储管理

    存储管理是操作系统非常重要的功能之一,本文主要介绍操作系统存储管理的基础知识,包括缓存相关知识.连续内存分配.伙伴系统.非连续内存分配.内存碎片等,并结合linux系统对这些知识进行简单的验证.文章内 ...

  9. 寄存器,cache、伙伴系统、内存碎片、段式页式存储管理

    cache.伙伴系统.内存碎片.段式页式存储管理 目录 分层的存储管理 cache 局部性原理 置换算法 写回策略 linux环境下的cache 连续内存分配与内存碎片 内部碎片与外部碎片 动态分区分 ...

随机推荐

  1. 【27.40%】【codeforces 599D】Spongebob and Squares

    time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...

  2. JAVA SE回顾及思考(3)——排序算法

    排序的算法是很多公司的笔试和面试题,个人感觉Java中其实无需使用这些排序方法,因为Java中已经为我们提供了很方便效率很高的sort()方法.但是不使用不能代表不需要学习这些算法,也不是仅仅为了面试 ...

  3. 入坑cordova

    原文:入坑cordova 因项目需要入坑cordova,奔跑吧骚年,目前只是要求安卓平台,下面都是以安卓为例 最好的学习资料还是官网. https://cordova.apache.org/ http ...

  4. android studio中文乱码各种情况的解决办法

    情况一:编辑器内的中文注释乱码. 解决办法:在界面的右下角找到 UTF-8 ,单击之,在弹出的列表中选中GBK 在弹出框内选中Reload 总结:导致这样的原因是你这个.java文件本身是GBK编码的 ...

  5. Android studio 无法启动安卓模拟器

    1.通过Android SDK Manager在extra中,找到并选中了那个Intel x86 Emulator Accelerator (HAXM) 2.手动启动HAXM    去对应的sdk\e ...

  6. C# WPF 多个window 相互覆盖的次序控制 不用topmost

    原文:C# WPF 多个window 相互覆盖的次序控制 不用topmost   WindowInteropHelper mianHanel = new WindowInteropHelper(Mai ...

  7. 【干货】Chrome插件(扩展)开发全攻略(转)

    写在前面 我花了将近一个多月的时间断断续续写下这篇博文,并精心写下完整demo,写博客的辛苦大家懂的,所以转载务必保留出处.本文所有涉及到的大部分代码均在这个demo里面:https://github ...

  8. 关闭Wind XP/Vista/Win7的DEP数据执行保护汇总(转)

    数据执行保护 (DEP) 是一种Windows安全机制,从Windows版本顺序上看是从Windows XP SP2开始引入,通过监视程序以确保它们使用的系统内存是安全的,帮助防止操作系统受到病毒和其 ...

  9. JIL 编译与 AOT 编译

    JIT:Just-in-time compilation,即时编译:AOT:Ahead-of-time compilation,事前编译. JVM即时编译(JIT) 1. 动态编译与静态编译 动态编译 ...

  10. automapper如何全局配置map条件过滤null值空值对所有映射起效

    原文 automapper如何全局配置map条件过滤null值空值对所有映射起效 我们在使用automapper的时候经常会遇到这样的问题:假设展示给用户的数据我们用UserDto类,User类就是我 ...