指令亂序有編譯期間指令亂序和執行期間指令亂序,編譯期間指令亂序能夠經過個人這篇博文了解一下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/ 轉載請註明出處