成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

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

vboy1010 / 1645人閱讀

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

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

文中提到:

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

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

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

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

?

重排序的背景

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

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

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

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

實(shí)例講解指令重排序原理

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

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

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

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

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

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

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

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

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

Incoherent instruction cache pipeline是跟JIT相關(guān)的類(lèi)型,作用是在執(zhí)行self-modifying code 時(shí)預(yù)防JIT沒(méi)有flush指令緩存。我不知道該類(lèi)型跟指令排序有什么關(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)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/69760.html

相關(guān)文章

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

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

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

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

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

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

    nihao 評(píng)論0 收藏0
  • Java多線程可見(jiàn)性談Happens-Before原則

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

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

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

    curlyCheng 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<