指令乱序有编译期间指令乱序和执行期间指令乱序,编译期间指令乱序能够经过个人这篇博文了解一下http://itblogs.ga/blog/20150329150706/,这篇文章里面简单谈下我对执行期间指令乱序的理解。linux
这里是我本身的搭建的博客地址,欢迎访问:http://itblogs.ga/blog/20150421092401/ 编程
文中一些观点是本身琢磨出来的,不保证正确,欢迎拍砖,纠正个人错误。若是深刻了解这块的知识,能够阅读文中提供的一些资料,比较权威。
缓存
摘自《Memory Ordering in Modern Microprocessors, Part I》多线程
Program order优化
the order in which the memory operations are specified in the code running on a given CPU.ui
Execution orderspa
the order in which the individual memory-reference instructions are executed on a given CPU. The execution order can differ from program order due to both compiler and CPU-implementation optimizations.线程
自己执行就乱序了,相对于program order,这是因为一、编译器优化后生成的二进制指令顺序和程序写的不一致;二、CPU自己优化致使乱序执行。
code
Perceived order:orm
the order in which a given CPU perceives its and other CPUs' memory operations. The perceived order can differ from the execution order due to caching, interconnect and memory-system optimizations. Different CPUs might well perceive the same memory operations as occurring in different orders.
Perceived order是在smp系统中才有的,举个例子,两个线程分别在两个core上运行:
A=0 B=0 Pthread1: store A=1 store B=1 Pthread2: load A=0 load B=1
明明pthread1先写的A,后写的B,按理说pthread2读到B=1了,A应该也是一才对。这是由于pthread2先看到了B的变化,还没看到A变化,对于pthread2来讲,他看到的pthread1的执行顺序是store B=1 store A=1。也就是说pthread1自己执行的顺序是正确的,但pthread2看到的pthrad1执行的顺序是乱的。
在单核时代,为了充分利用CPU资源,computer architects have used instruction-level parallelization techniques to improve processor perfor mance. Instruction-level parallelism (ILP), also known as dynamic, or out-of-order execution, gives the CPU the ability to reorder instructions in an optimal way to eliminate pipeline stalls. The goal of ILP is to increase the number of instructions that are executed by the processor on a single clock cycle. 摘自 《Multi-core programming Increasing Performance through Software Multi-threading》.
单核时代Out of order带来的问题
在访问设备时,一般会有这样的需求,先向端口A写入个数据,设备将结果写入到端口B,程序从端口B读取数据。
write porta; read portb;
这样的程序是严重依赖于顺序的,若是顺序反了,就读不到正确的值,问题就大了。
怎么解决
解决这个问题的方法就是引入了memory barrier,CPU提供memory barrier指令,保证了memory barrier先后的指令的执行顺序。
write porta; memory barrier; read portb;
这就是为何咱们在阅读驱动源码时,为何遇到相似mb(); rmb();等的语句,这都是linux内核提供的memory barrier,封装了底层CPU指令。 关于memory barrier,《linux kernel source -- Documentation/memory-barriers.txt》是个很好的文档。
个人疑问
《linux kernel source -- Documentation/memory-barriers.txt》中有这样一段描述:
Memory barriers are only required where there's a possibility of interaction between two CPUs or between a CPU and a device. If it can be guaranteed that there won't be any such interaction in any particular piece of code, then memory barriers are unnecessary in that piece of code.
单cpu 多线程不考虑吗?
A = 0 B = 0 C[10] = {}; =================================== thread1 | thread2 | if (A==1) { B = C; | access B A = 1; | }
如上代码,若是thread1的执行顺序乱了,对于thread2,后果是很严重的。
对于这个问题,始终没有找到答案,我也只能尝试着回答一下。在单核时代,内存模型比较简单,遵循了sequential consistency《Shared Memory Consistency Models:A Tutorial》,即对内存操做会按顺序执行。而读写设备端口时,虽然发出了写端口的操做,但写操做没有完成,程序执行了读端口的命令,致使读的已经完成,而写还没完成,而出现乱序。内存系统若是有这样的状况发生,他能作到等写完再读,而对于独立的设备,他也保证这个的话,显然会比较复杂。
到了多核时代,首先不仅一个CPU执行指令了,而后,内存系统也复杂的多了,有一级、二级、三级缓存,而且每一个核都有本身的缓存。
不一样的读指令,执行的时间就会不一样,有直接拿本身的缓存的,有在内存中读的。指令执行的时间不一样,必然致使流水线上指令进一步乱序。
而后是写指令,指令执行完了,但写的操做不必定执行完了,可能只写在本身缓存上了,须要会写到内存中,可能还须要同步到其余的CPU的缓存中。写同步的速度不一致,也就带来了咱们以前提到的Perceived order 问题。
固然,若是内存系统还保证sequential consistency,那么这些问题就不存在了,可是多核状况下保证sequential consistency远远要比单CPU要复杂,多核并行的优点就彻底体现不出来了,基本上商业CPU都没有保证sequential consistency。
针对这样的问题,业界提成了多个内存一致性模型,不一样的CPU有不一样的处理,感兴趣的能够搜索如下文章了解:
《Shared Memory Consistency Models:A Tutorial》
《Memory Ordering in Modern Microprocessors, Part I》
怎么办
咱们怎么应对呢,依然是使用memory barrier,对照于单核时代的mb,rmb,wmb,smp系统中使用smp_mb等,解决smp系统中的指令乱序问题。
大部分编程中不会涉及到memory barrier的问题,而且一些原子操做和全部同步锁操做中帮咱们处理了指令乱序的问题。但若是咱们在并行编程中使用效率更高的无锁编程,那么就必须了解这方面的知识,摸清CPU的特性,正确的使用memory barrier。最好的方式是像内核那样,使用宏定义定义全部的memory barrier。在全部须要使用的地方都使用,只是在一些平台上,内存模型会更强一些,不须要,那就定义为空语句。
我总结的比较浅,毕竟我也只是个入门,把这几天的看的东西总结如下,没有涉及很深。
若是你须要了解的更加深刻,如下材料值得阅读:
linux kernel source -- Documentation/memory-barriers.txt
Shared Memory Consistency Models:A Tutorial
Memory Ordering in Modern Microprocessors, Part I
Memory Consistency Models for Shared-Memory Multiprocessors
Memory Consistency and Event Ordering in Scalable Shared-Memory Multiprocessors
Multi-core programming Increasing Performance through Software Multi-threading
原文连接:http://itblogs.ga/blog/20150421092401/ 转载请注明出处