編譯器優化重排序和指令級並行重排序不會影響程式的結果,因此程式設計師需要著重處理的是記憶體系統重排序帶來的問題。
1.編譯器優化的重排:
編譯器在不改變單執行緒程式語義的前提下,可以重新安排語句的執行順序
2.指令級並行的重排:
為了提高cpu的執行效率,現代的cpu基本上都支援指令流水線。
2.1 指令流水線:
一條指令要執行要經過3個階段:取指令、解碼、執行,每個階段都要花費乙個機器週期,如果沒有採用流水線技術,那麼這條指令執行需要3個機器週期;如果採用了指令流水線技術,那麼當這條指令完成「取指」後進入「解碼」的同時,下一條指令就可以進行「取指」了,這樣就提高了指令的執行效率。
指令步驟的並行。常見的六級流水線將指令流的處理過程劃分為取指(fi)、解碼(di)、計算運算元位址(co)、取運算元(fo)、執行指令(ei)、寫運算元(wo)等幾個並行處理的過程段。這就是指令6級流水時序。在這個流水線中,處理器有六個操作部件,同時對這六條指令進行加工,加快了程式的執行速度。幾乎所有的高效能計算機都採用了指令流水線。
2.2 流水線停頓:
處理器的流水線設計中有流水線中的衝突(hazards)問題:主要分為資源衝突和資料衝突。
2.3 停頓的優化:
3. 記憶體系統的重排:
3.1 memory bank 的劃分 :
一般 memory bank 是按 cache address 來劃分的。比如 偶數 adress 0×12345000 分到 bank 0, 奇數 address 0×12345100 分到 bank1
3.2 重排序分析:
理想的記憶體訪問指令順序:
cpu0 往 cache address 0×12345000 寫入乙個數字 1 。因為address 0×12345000 是偶數,所以值被寫入 bank0.
cpu1 讀取 bank0 address 0×12345000 的值,即數字1 。
cpu0 往 cache 位址 0×12345100 寫入乙個數字 2 。因為address 0×12345100 是奇數,所以值被寫入 bank1.
cpu1 讀取 bank1 address 0×12345100 的值,即數字2 。
重排序後的記憶體訪問指令順序:
cpu0 準備往 bank0 address 0×12345000 寫入數字 1 。
cpu0 檢查 bank0 的可用性。發現 bank0 處於 busy 狀態。
cpu0 為了防止 cache 等待,發揮最大效能,將記憶體訪問指令重排序。即先執行後面的 bank1 address 0×12345100 數字2 的寫入請求。
cpu0 檢查 bank1 可用性,發現bank1 處於 idle 狀態。
cpu0 將數字2 寫入 bank 1 address 0×12345100 。
cpu1 來讀取 0×12345000 ,未讀到 數字1 ,出錯。
cpu0 繼續檢查 bank0 的可用性,發現這次 bank0 可用了,然後將數字1 寫入 0×12345000 。
cpu1 讀取 0×12345100 ,讀到數字2 ,正確。
從上述觸發步驟中,可以看到第 3 步發生了指令重排序,並導致第 6 步讀到錯誤的資料。
通過對指令重排,cpu 可以獲得更快地響應速度, 但也給編寫併發程式的程式設計師帶來了諸多挑戰。
3.3 解決重排序帶來的問題:
記憶體屏障是用來防止cpu 出現指令重排序的利器之一。
storeload barriers是乙個「全能型」的屏障,它同時具有其他3個屏障的效果。現代的多處 理器大多支援該屏障(其他型別的屏障不一定被所有處理器支援)。執行該屏障開銷會很昂 貴,因為當預處理器通常要把寫緩衝區中的資料全部重新整理到記憶體中(buffer fully flush)。
cpu指令重排序的原理
目錄 1.重排序場景 2.追根溯源 3.快取一致性協議 4.重排序原因 一 重排序場景 class resortdemo public void reader 當兩個執行緒 a 和 b,a 首先執行writer 方法,隨後 b 執行緒接著執行 reader 方法。執行緒b在執行操作4時,能否看到執行...
執行緒指令重排
jvm為優化執行效率對執行緒內的執行順序進行重排,對單執行緒來說執行指令重排並不會影響程式從上到下執行的 邏輯。但是在多執行緒的情況下,則可能會出現問題。程式順序原則 乙個執行緒內保證語義的序列性 volatile規則 volatile變數的寫,先發生於讀 鎖規則 解鎖 unlock 必然發生在隨後...
HappenBefore指令重排
你寫的 很可能根本沒按你期望的順序執行,因為編譯器和cpu會嘗試重排指令使得 更快地執行。在虛擬機器層面,為了盡可能減少記憶體操作速度遠慢於cpu執行速度所帶來的cpu空置的影響,虛擬機會按照自己的一些規則將程式編寫順序打亂 即寫在後面的 在時間順序上可能會先執行,而寫在前面的 會後執行 以盡可能充...