并发中的一些基本概念

来源:互联网 发布:无人机航迹规划算法 编辑:程序博客网 时间:2024/05/30 23:01

背景

在多核多线程的并发编程中,我们经常会碰到一些概念,比如说out of order execution, memory consistency, cache coherence, memory model等,这里我对这些概念做一些简单的总结和介绍。

为什么会有乱序执行

乱序执行(out of order execution)的来源通常有2种,一种是来自编译器,一种来自CPU。之所以会发生乱序,简单点来讲就是为了更高的执行效率。编译器通过乱序可以生成更优化的代码,CPU乱序可以更好的利用硬件。比如说,当需要加载的数据不在cache中,CPU可以跳过等待加载的过程,继续后面其他的写入数据或者加载数据。

Memory Consistency

Memory Consistency通常指的是CPU执行代码时所要遵循的一些限制。前面我们讲过CPU在执行代码时又可能会发生乱序,如果CPU的乱序没有任何的限制,那我们根本无法编写多线程程序,因为我们根本没有办法预测代码以何种方式执行。而memory consistency则对CPU的乱序做了某些限制,从而让我们能推理程序可能的执行结果。这里我们以sequential consistency为例来说明。关于sequantial consistency的定义网上有很多说明,这个我不在赘述,简单讲就是2点:

  1. 所有的指令执行顺序符合某种全序
  2. 在这个全序中每个线程的指令符合program order

有了这2点保证,下面的代码段就不会出现r1=0 and r2=0 的结果:

thread 1: a = 4;r1 = b;thread 2:b = 7;r2 = a;

Sequential consistency是一个比较强的内存模型,现实中的CPU基本上没有遵循这个模型的,因为这个模型上能做的优化太少。通常来说,CPU在提供一定的内存模型之外,还会提供一定的指令来允许指定程序的执行顺序,这样的指令通常称为memory barrier或者memory fence。

cache coherence

cache coherence对于程序来说是不可见的。cache的引入主要是为了解决CPU和内存之间速度不匹配的问题。由于访问内存速度较慢,CPU的直接操作数据的对象就变成了cache而不是内存。这就带来一些问题,因为每个core会有自己私有的cache,当core 1改变了数据写入cache而没有写入内存,core 2中的cache就会有过期数据,如果不做任何处理,cache的引入就会导致错误。cache coherence protocol就是为不同cache之间的数据的一致性而设计的,有了它的存在cache只会影响程序执行速度而不是正确性。

Memory Model

这里的memory model指的是编程语言的memory model。我们所使用的高级编程语言如java, c++, c等都有一个abstract machine model,编程语言的memory model就是用来指定程序的合法的执行顺序。对于java来说,memory model就是用来指定虚拟机执行程序的时候哪些优化是合法的。对于c/c++这样的语言来说,memory model会限制编译器生成程序的时候所做的优化,以及在目标平台上应该结合目标平台提供的memory consistency和指令来实现。

Memory Barrier

Memory Barrier是编程语言memory model的一部分,没有一个统一的标准来规定memory barrier的种类,但是通常情况下会有如下几种:

  1. load load
  2. store store
  3. load store
  4. store load
  5. data dependency
  6. full barrier

这几种barrier的具体含义很容易查到,这里我就不再叙述。当我们在使用memory barrier推理程序的正确性的时候,有几点需要注意:

  1. memory barrier必须成对使用才有效果。比如说如下示例:

    a = 1;store store barrierb = 2;
    r1 = b;r2 = a;

    在这个示例中2段程序分别由不同的线程执行,对于第二段程序,当r1 = 2时,r2读到的值不一定是1,要想达到想要的效果,必须在2次读取之间加入一个load load barrier

  2. 尽量使用memory barrier提供的语义保证来推理程序的执行逻辑,而不要尝试将其对应到相应平台的指令来推理。这个道理同样适用于memory model里所提供的语义。 网络上有很多关于memory model和memory barrier的资料,但一个常见的错误是在推理程序执行逻辑的时候喜欢使用具体的指令集而不是形式化的memory model所提供的语义。当然了解一些硬件平台的指令和memory model对你理解编程语言的memory model会有帮助,但还是应该使用形式化的memory model来推理程序的正确性。

0 0
原创粉丝点击