不得不了解的CPU知识

CPU的发展史

CPU的工作原理

总的来说,CPU从内存中一条一条地取出指令和相应的数据,按指令操作码的规定,对数据进行运算处理,直到程序执行完毕为止。

CPU指令周期

指令周期是取出并执行一条指令的时间。指令周期常常有若干个CPU周期,CPU周期也称为机器周期,由于CPU访问一次内存所花费的时间较长,因此通常用内存中读取一个指令字的最短时间来规定CPU周期。

一条指令还是相当复杂的,处理器在一个时钟周期内肯定是完不成的,可能需要好多个时钟周期来完成执行。如果这样让处理器执行完一条指令,再去执行另一条,处理器的效率是很低的,假如一条指令是5个时钟周期完成,对于500MHZ的处理器串行运行指令,1秒内取指100000000次。

因此处理器引入了流水线技术,将一条指令划分为多个功能,由不同的功能部件来执行,并且这些功能部件可以并行工作。

流水线技术

CPU在工作时,需要将一条指令分为多个步骤依次执行(注意硬件不同有可能不一样),由于每一个步会使用到不同的硬件操作,比如取指时会只有PC寄存器和存储器,译码时会执行到指令寄存器组,执行时会执行ALU(算术逻辑单元)、写回时使用到寄存器组。为了提高硬件利用率,CPU指令是按流水线技术来执行的,如下:

从图中可以看出当指令1还未执行完成时,第2条指令便利用空闲的硬件开始执行,这样做是有好处的,如果每个步骤花费1ms,那么如果第2条指令需要等待第1条指令执行完成后再执行的话,则需要等待5ms,但如果使用流水线技术的话,指令2只需等待1ms就可以开始执行了,这样就能大大提升CPU的执行性能。

理想情况下,CPU按照流水线执行指令,然而指令流水线除了在资源不足的情况下会卡住之外,指令之间的相关性也是导致流水线阻塞的重要原因。

虽然流水线技术可以大大提升CPU的性能,但不幸的是一旦出现流水中断,所有硬件设备将会进入一轮停顿期,当再次弥补中断点可能需要几个周期,这样性能损失也会很大,就好比工厂组装手机的流水线,一旦某个零件组装中断,那么该零件往后的工人都有可能进入一轮或者几轮等待组装零件的过程。因此我们需要尽量阻止指令中断的情况,指令重排就是其中一种优化中断的手段。

指令乱序(cpu在进行读等待的同时执行指令,是CPU乱序的根源,但目的不是为了乱,而是为了提高执行效率)

指令流水线并不是串行的,并不会因为一个耗时很长的指令在“执行”阶段呆很长时间,而导致后续的指令都卡在“执行”之前的阶段上。相反,流水线是并行的,多个指令可以同时处于同一个阶段,只要CPU内部相应的处理部件未被占满即可。

然而,这样一来,乱序可能就产生了。比如一条加法指令原本出现在一条除法指令的后面,但是由于除法的执行时间很长,在它执行完之前,加法可能先执行完了。再比如两条访存指令,可能由于第二条指令命中了cache而导致它先于第一条指令完成。

一般情况下,指令乱序并不是CPU在执行指令之前刻意去调整顺序。CPU总是顺序的去内存里面取指令,然后将其顺序的放入指令流水线。但是指令执行时的各种条件,指令与指令之间的相互影响,可能导致顺序放入流水线的指令,最终乱序执行完成。这就是所谓的“顺序流入,乱序流出”。

CPU的乱序执行并不是任意的乱序,而是以保证程序上下文因果关系为前提的。有了这个前提,CPU执行的正确性才有保证。

相比于CPU的乱序,编译器的乱序才是真正对指令顺序做了调整。但是编译器的乱序也必须保证程序上下文的因果关系不发生改变。

禁止乱序

CPU规则:CPU的速度至少比内存快100倍,为了提升效率,会打乱原来的执行效率,会在一条指令执行过程中(比如去内存读数据,大概慢100多倍),去同时执行另一条指令,前提是两条指令没有依赖关系(洗茶壶/烧水-茶叶入壶-煮茶-喝茶)。洗茶壶/烧水两个步骤就没有以来关系。

CPU层面:Intel -> 原语(mfence(内存屏障) lfence(loadfence)(读屏障) sfence(storefence)(写屏障)) 或者锁总线

有序性保障:Intel lock汇编指令

原子指令:如x86上的“lock....”指令是一个Full Barrier,执行时会锁住内存子系统(锁总线)来确保执行顺序,甚至跨越多个CPU。Software Locks 通常使用了内存屏障或原子性指令来实现变量可见性和程序顺序

JVM层级:

8个hanppens-before原则:(JVM规定重排序必须遵循的规则)

1.代码执行顺序原则,代码的执行顺序,编写在前面的发生在编写在后面的之前
2.锁原则,unlock后于lock
3.线程启动原则,start方法优先于run方法
4.对象销毁原则,初始化必须发生在finalize之前
5.线程终结原则,所有操作发生在线程死亡之前
6.volatile修饰的变量,写操作优先于读操作
7.传递性原则,操作A先于B,B先于C,那么A肯定先于C
8.线程中断原则,interrupt这个动作,必须发生在捕获该动作之前
代码执行顺序,锁原则,线程原则(3个,start优先于run,interrupt优先于捕获,线程终结在最后),对象的生命周期(初始化优先于finnalize),传递性原则,volatile

 4个内存屏障 (LL(loadload) LS(loadstore) SL(storeload) SS(storestore))

as-if-serial : 不管硬件什么顺序,单线程执行的结果不变,看上去像是serial

参考:http://m.elecfans.com/article/645741.html

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值