日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

内存屏障,先看这篇文章

發(fā)布時間:2023/12/20 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 内存屏障,先看这篇文章 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

剛看到這個詞的時候,我以為是白內(nèi)障,然后查了很多資料,才理解內(nèi)存屏障是干嘛的,我就不像很多其他文章說得那么多了,我希望我說得簡單一些,讓大家看了我的文章都知道這個是怎么回事。

說到內(nèi)存屏障,我們先從CPU性能優(yōu)化說起

性能優(yōu)化的方法一,緩存

CPU的速度很快,到底有多快?我們就用光速來比喻CPU的執(zhí)行速度吧,反正就是執(zhí)行讀寫很快,但是CPU速度很快,內(nèi)存的速度很慢,怎么辦?

這時候,高速緩存出現(xiàn)了「先不抬杠說寄存器哈」。比如有一個變量a ,CPU在很長一段時間內(nèi)都需要使用它,如果把他放在內(nèi)存里面的話,每次讀寫的速度都很慢,這樣嚴(yán)重拖慢了CPU的執(zhí)行速度。

所以就出現(xiàn)了 緩存

緩存也是分類的,緩存分成了三類,我簡單說明下

緩存同步協(xié)議MESI如果在4個CPU在各自的L1 里面都有一個變量 i ,他們要把這個變量i寫入到內(nèi)存里面去,是以哪一個為準(zhǔn)呢?

這個時候就需要緩存的同步協(xié)議,每個cpu對緩存里面的變量操作的時候,要通知其他CPU,讓他們知道當(dāng)前的狀態(tài)。

CPU不僅需要發(fā)消息給其他CPU告訴他們狀態(tài),同時也要接收其他CPU發(fā)出來的狀態(tài)。

這樣做的最終目的,就是為了保證CPU對變量操作的一致性

CPU性能優(yōu)化的方法二,運行時指令重排

指令重排是個有意思的事情,如果把CPU當(dāng)成是一個人的話,他也是有自己的意識的,存在意識的東西,就會存在自己做事情的方法,比如,我今天要去打籃球,還要去幫媽媽打醬油,我是先打籃球還是先打醬油,因為個人的意識不同,做事情的先后順序也存在差異。

為什么出現(xiàn)指令重排?如果有一個CPU,我們假設(shè)是CPU0吧,它在寫緩存的的某個區(qū)塊的時候,發(fā)現(xiàn)這個緩存位置剛好被CPU1正常操作,那他怎么辦?有兩種方法,一種是等待CPU1執(zhí)行結(jié)束后自己再執(zhí)行,還有一種方法就是先去干其他的事情,很明顯,CPU為了提高自己的性能,它會選擇第二種方法,就是先去干其他的事情,干其他的事情,就出現(xiàn)上面描述的情況,指令重排了。

所以我們會有一個疑問?代碼是按照程序員的想法去執(zhí)行的呢?還是按照CPU的想法去執(zhí)行的呢?回答當(dāng)然是需要按照程序員的意識去執(zhí)行的。

所以要求,指令重排遵循as-if-serial語義這個是什么意思呢?就是說指令重排的結(jié)果不能影響程序員預(yù)期的結(jié)果,比如上面的代碼,重排后就會出現(xiàn)問題,那么CPU就不能對指令進(jìn)行重排。

注意,上面所說的as-if-serial語義針對的是單核CPU來說

但是如果是下面的代碼

a = 100; b = c;

上面兩條語句不存在依賴關(guān)系,它們可以進(jìn)行指令重排,因為重排后不會影響最后的執(zhí)行結(jié)果。

高速緩存和指令重排序(reordings)存在的問題

緩存機制和指令重排都是為了CPU運算的性能優(yōu)化。會出現(xiàn)兩個問題。1、緩存和內(nèi)存的數(shù)據(jù)并不是時實同步的,同一個內(nèi)存地址,不同的CPU看到的內(nèi)存值是不一樣的。因為CPU運行速度很快,假設(shè),CPU0 讀 地址 0x2345 的時候值為 1,這個時候,CPU1向 0x2345寫入了 2,CPU2再讀這個內(nèi)存 0x2345 的值的時候,發(fā)現(xiàn)它變成2了。所以就有問題了

出現(xiàn)的問題是同一個時間點上,不同的CPU看到的同一個內(nèi)存地址數(shù)據(jù)不一樣

2、我們指令重排說的as-if-serial語義只是針對單個CPU,那多個CPU呢?會出現(xiàn)什么問題

看下面的例子:

看上面圖片

CPU0 要執(zhí)行兩條指令,CPU1也要執(zhí)行兩條指令,但是如果他們執(zhí)行的先后順序不同,那么x和y的結(jié)果也將存在差異。

第一種情況如下圖執(zhí)行順序會導(dǎo)致 x = 0 , y = 1。

第二種情況如下圖執(zhí)行順序會導(dǎo)致 x =1,y = 0。第三種情況如下圖執(zhí)行順序會導(dǎo)致 x = 1,y=1。

結(jié)果跟程序員的預(yù)期不符合 出現(xiàn)的問題是,多個CPU,也就是我們經(jīng)常所說的SMP系統(tǒng)下,會出現(xiàn)結(jié)果和預(yù)期不一致的問題

最后說內(nèi)存屏障(Memory Barrier)

內(nèi)存屏障就是用來解決上面兩個問題的。這個是CPU廠商來搞定的。

  • 寫內(nèi)存屏障(Store Memory Barrier) 寫內(nèi)存屏障的意思就是在寫內(nèi)存的后面加入指令 Store Barrier ,如果CPU有讀的也有寫的,加了這條指令,就保證先執(zhí)行寫入而不去做指令重排,這種顯示調(diào)用可以讓其他線程看到。其他線程會等這個執(zhí)行結(jié)束后再去操作,既然是等待,那也是降低性能的,好吧,降低性能也是沒有辦法的事情了。

就拿上面的 圖片來說明A = 1 B = 1 這兩個是寫操作,我們加上寫內(nèi)存屏障,即使其他CPU有讀的指令,我們需要等待這個寫完成后,再進(jìn)行讀操作。

  • 讀內(nèi)存屏障 (Load Memory Barrier) 在讀指令之前插入Load Barrier,可以讓高速緩存中的數(shù)據(jù)失效,強制從內(nèi)存加載最新的數(shù)據(jù),讓CPU緩存和主內(nèi)存保持一致,避免了緩存導(dǎo)致的一致性問題。

void executedOnCpu0() {value = 10;/*在更新數(shù)據(jù)之前必須將所有存儲緩存(store buffer)中的指令執(zhí)行完畢。*/storeMemoryBarrier();finished = true; } void executedOnCpu1() {while(!finished);/*在讀取之前將所有失效隊列中關(guān)于該數(shù)據(jù)的指令執(zhí)行完畢。*/loadMemoryBarrier();assert value == 10; }

總結(jié)

CPU為了性能,發(fā)明了緩存和指令重排,但是又因為緩存和指令重排出現(xiàn)了新的問題,因為新的問題出現(xiàn),聰明的人類又發(fā)明了內(nèi)存屏障,之所謂,兵來將擋水來土掩就是這個道理。

文章是整理了自己看到資料的很多見解,后續(xù)會發(fā)新的文章進(jìn)一步講解,當(dāng)然了,或者也會不發(fā),我就是一只漂亮的鴿子,我鴿呀鴿呀鴿,祝大家周末愉快。


掃碼或長按關(guān)注

回復(fù)「?籃球的大肚子」進(jìn)入技術(shù)群聊

總結(jié)

以上是生活随笔為你收集整理的内存屏障,先看这篇文章的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。