成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

從JVM并發(fā)看CPU內(nèi)存指令重排序

vboy1010 / 1535人閱讀

摘要:處理器通過緩存能夠從數(shù)量級上降低內(nèi)存延遲的成本這些緩存為了性能重新排列待定內(nèi)存操作的順序。從上述觸發(fā)步驟中,可以看到第步發(fā)生了指令重排序,并導(dǎo)致第步讀到錯誤的數(shù)據(jù)。內(nèi)存屏障是用來防止出現(xiàn)指令重排序的利器之一。

這兩天,我拜讀了 Dennis Byrne 寫的一片博文Memory Barriers and JVM Concurrency (中譯文內(nèi)存屏障與JVM并發(fā))。

文中提到:

對主存的一次訪問一般花費硬件的數(shù)百次時鐘周期。處理器通過緩存(caching)能夠從數(shù)量級上降低內(nèi)存延遲的成本這些緩存為了性能重新排列待定內(nèi)存操作的順序。也就是說,程序的讀寫操作不一定會按照它要求處理器的順序執(zhí)行。

這段話是作者對內(nèi)存屏障重要性的定義。通過cache降低內(nèi)存延遲,這句話很好理解。但后面那句“為了性能重排序內(nèi)存操作順序”,讓沒學(xué)好微機(jī)原理的我倍感疑惑。

CPU為何要重排序內(nèi)存訪問指令?在哪種場景下會觸發(fā)重排序?作者在文中并未提及。

為了解答疑問,我在網(wǎng)上查閱了一些資料,在這里跟大家分享一下。

?

重排序的背景

我們知道現(xiàn)代CPU的主頻越來越高,與cache的交互次數(shù)也越來越多。當(dāng)CPU的計算速度遠(yuǎn)遠(yuǎn)超過訪問cache時,會產(chǎn)生cache wait,過多的cache wait就會造成性能瓶頸。
針對這種情況,多數(shù)架構(gòu)(包括X86)采用了一種將cache分片的解決方案,即將一塊cache劃分成互不關(guān)聯(lián)地多個 slots (邏輯存儲單元,又名 Memory Bank 或 Cache Bank),CPU可以自行選擇在多個 idle bank 中進(jìn)行存取。這種 SMP 的設(shè)計,顯著提高了CPU的并行處理能力,也回避了cache訪問瓶頸。

Memory Bank的劃分
一般 Memory bank 是按cache address來劃分的。比如 偶數(shù)adress 0×12345000分到 bank 0, 奇數(shù)address 0×12345100分到 bank1。

重排序的種類
編譯期重排。編譯源代碼時,編譯器依據(jù)對上下文的分析,對指令進(jìn)行重排序,以之更適合于CPU的并行執(zhí)行。

運行期重排,CPU在執(zhí)行過程中,動態(tài)分析依賴部件的效能,對指令做重排序優(yōu)化。

實例講解指令重排序原理

為了方便理解,我們先來看一張CPU內(nèi)部結(jié)構(gòu)圖。

從圖中可以看到,這是一臺配備雙CPU的計算機(jī),cache 按地址被分成了兩塊 cache banks,分別是cache bank0cache bank1。

理想的內(nèi)存訪問指令順序:
1,CPU0往cache address 0×12345000 寫入一個數(shù)字 1。因為address 0×12345000是偶數(shù),所以值被寫入 bank0.
2,CPU1讀取 bank0 address 0×12345000 的值,即數(shù)字1。
3,CPU0往 cache 地址 0×12345100 寫入一個數(shù)字 2。因為address 0×12345100是奇數(shù),所以值被寫入 bank1.
4,CPU1讀取 bank1 address 0×12345100 的值,即數(shù)字2。

重排序后的內(nèi)存訪問指令順序:
1,CPU0 準(zhǔn)備往 bank0 address 0×12345000 寫入數(shù)字 1。
2,CPU0檢查 bank0 的可用性。發(fā)現(xiàn) bank0 處于 busy 狀態(tài)。
3, CPU0 為了防止 cache等待,發(fā)揮最大效能,將內(nèi)存訪問指令重排序。即先執(zhí)行后面的 bank1 address 0×12345100 數(shù)字2的寫入請求。
4,CPU0檢查 bank1 可用性,發(fā)現(xiàn)bank1處于 idle 狀態(tài)。
5,CPU0 將數(shù)字2寫入 bank 1 address 0×12345100。
6,CPU1來讀取 0×12345000,未讀到 數(shù)字1,出錯。
7, CPU0 繼續(xù)檢查 bank0 的可用性,發(fā)現(xiàn)這次bank0 可用了,然后將數(shù)字1寫入 0×12345000。
8, CPU1 讀取 0×12345100,讀到數(shù)字2,正確。

從上述觸發(fā)步驟中,可以看到第 3 步發(fā)生了指令重排序,并導(dǎo)致第 6步讀到錯誤的數(shù)據(jù)。

通過對指令重排,CPU可以獲得更快地響應(yīng)速度,但也給編寫并發(fā)程序的程序員帶來了諸多挑戰(zhàn)。
內(nèi)存屏障是用來防止CPU出現(xiàn)指令重排序的利器之一。
通過這個實例,不知道你對指令重排理解了沒有?

不同架構(gòu)下的指令重排優(yōu)化

X86僅在 Stores after loadsIncoherent instruction cache pipeline 中會觸發(fā)重排。

Stores after loads的含義是在對同一個地址進(jìn)行讀寫操作時,寫入在讀取后面,允許重排序。即滿足弱一致性(Weak Consistency),這是最可被接受的類型,不會造成太大的影響。

Incoherent instruction cache pipeline是跟JIT相關(guān)的類型,作用是在執(zhí)行self-modifying code 時預(yù)防JIT沒有flush指令緩存。我不知道該類型跟指令排序有什么關(guān)系,既然不在本文涉及范圍內(nèi),就不做深入探討了。

參考資料

http://kenwublog.com/docs/memory.barrier.ppt

http://kenwublog.com/docs/memory.model.instruction.reordering.and.store.atomicity.pdf

http://kenwublog.com/docs/memory.ordering.in.modern.microprocessor.pdf

http://en.wikipedia.org/wiki/Memory_ordering

http://en.wikipedia.org/wiki/Memory_Bank

via ifeve

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/69760.html

相關(guān)文章

  • Java 并發(fā)編程(學(xué)習(xí))

    摘要:并發(fā)編程的挑戰(zhàn)并發(fā)編程的目的是為了讓程序運行的更快,但是,并不是啟動更多的線程就能讓程序最大限度的并發(fā)執(zhí)行。的實現(xiàn)原理與應(yīng)用在多線程并發(fā)編程中一直是元老級角色,很多人都會稱呼它為重量級鎖。 并發(fā)編程的挑戰(zhàn) 并發(fā)編程的目的是為了讓程序運行的更快,但是,并不是啟動更多的線程就能讓程序最大限度的并發(fā)執(zhí)行。如果希望通過多線程執(zhí)行任務(wù)讓程序運行的更快,會面臨非常多的挑戰(zhàn):(1)上下文切換(2)死...

    NervosNetwork 評論0 收藏0
  • (七)Volatile的作用及原理

    摘要:文章簡介分析的作用以及底層實現(xiàn)原理,這也是大公司喜歡問的問題內(nèi)容導(dǎo)航的作用什么是可見性源碼分析的作用在多線程中,和都起到非常重要的作用,是通過加鎖來實現(xiàn)線程的安全性。而的主要作用是在多處理器開發(fā)中保證共享變量對于多線程的可見性。 文章簡介 分析volatile的作用以及底層實現(xiàn)原理,這也是大公司喜歡問的問題 內(nèi)容導(dǎo)航 volatile的作用 什么是可見性 volatile源碼分析 ...

    marek 評論0 收藏0
  • Java 并發(fā)編程

    摘要:并發(fā)編程的核心是為了提高電腦資源的利用率,因為現(xiàn)代操作系統(tǒng)都是多核的,可以同時跑多個線程。合理配置線程池,密集型任務(wù)配置少數(shù)線程池如個數(shù),密集型任務(wù)配置多一點的線程池如個數(shù),其次是使用有界隊列即使發(fā)現(xiàn)錯誤。 并發(fā)編程的核心是為了提高電腦資源的利用率,因為現(xiàn)代操作系統(tǒng)都是多核的,可以同時跑多個線程。那么是不是線程越多越好? 由于線程的切換涉及上下文的切換,所謂上下文就是線程運行時需要的資...

    nihao 評論0 收藏0
  • Java多線程可見性談Happens-Before原則

    摘要:本文會先闡述在并發(fā)編程中解決的問題多線程可見性,然后再詳細(xì)講解原則本身。所以與內(nèi)存之間的高速緩存就是導(dǎo)致線程可見性問題的一個原因。原則上面討論了中多線程共享變量的可見性問題及產(chǎn)生這種問題的原因。 Happens-Before是一個非常抽象的概念,然而它又是學(xué)習(xí)Java并發(fā)編程不可跨域的部分。本文會先闡述Happens-Before在并發(fā)編程中解決的問題——多線程可見性,然后再詳細(xì)講解H...

    MyFaith 評論0 收藏0
  • 并發(fā)編程的藝術(shù)

    摘要:假設(shè)不發(fā)生編譯器重排和指令重排,線程修改了的值,但是修改以后,的值可能還沒有寫回到主存中,那么線程得到就是很自然的事了。同理,線程對于的賦值操作也可能沒有及時刷新到主存中。線程的最后操作與線程發(fā)現(xiàn)線程已經(jīng)結(jié)束同步。 很久沒更新文章了,對隔三差五過來刷更新的讀者說聲抱歉。 關(guān)于 Java 并發(fā)也算是寫了好幾篇文章了,本文將介紹一些比較基礎(chǔ)的內(nèi)容,注意,閱讀本文需要一定的并發(fā)基礎(chǔ)。 本文的...

    curlyCheng 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<