緩存一致性

前言

該文章也是在網(wǎng)上收集資料和整理出來的,具體參考那些博客也不記得了請原諒齿诞。

文章不確定是否完全正確骂租,只是自我感覺能說清楚,有錯誤請指正IK薰巍糙置!

基本概念

本文是關(guān)于CPU緩存的快速入門是目。我假設(shè)你已經(jīng)有了基本概念标捺,但你可能不熟悉其中的一些細節(jié)。(如果你已經(jīng)熟悉了亡容,你可以忽略這部分。)

在現(xiàn)代的CPU(大多數(shù))上茂缚,所有的內(nèi)存訪問都需要通過層層的緩存來進行屋谭。也有些例外,比如悔耘,對映射成內(nèi)存地址的I/O口我擂、寫合并(Write-combined)內(nèi)存,這些訪問至少會繞開這個流程的一部分校摩。但這兩者都是罕見的場景(意味著絕大多數(shù)的用戶態(tài)代碼都不會遇到這兩種情況),所以在本文中备籽,我將忽略這兩者分井。

CPU的讀/寫(以及取指令)單元正常情況下甚至都不能直接訪問內(nèi)存——這是物理結(jié)構(gòu)決定的;CPU都沒有管腳直接連到內(nèi)存珠闰。相反瘫辩,CPU和一級緩存(L1 Cache)通訊坛悉,而一級緩存才能和內(nèi)存通訊承绸。大約二十年前,一級緩存可以直接和內(nèi)存?zhèn)鬏敂?shù)據(jù)轩猩。如今荡澎,更多級別的緩存加入到設(shè)計中,一級緩存已經(jīng)不能直接和內(nèi)存通訊了摩幔,它和二級緩存通訊——而二級緩存才能和內(nèi)存通訊〗褂埃或者還可能有三級緩存封断。你明白這個意思就行。

緩存是分“段”(line)的椒涯,一個段對應(yīng)一塊存儲空間回梧,大小是32(較早的ARM、90年代/2000年代早期的x86和PowerPC)狱意、64(較新的ARM和x86)或128(較新的Power ISA機器)字節(jié)。每個緩存段知道自己對應(yīng)什么范圍的物理內(nèi)存地址财骨,并且在本文中藏姐,我不打算區(qū)分物理上的緩存段和它所代表的內(nèi)存,這聽起來有點草率捌臊,但是為了方便起見兜材,還是請熟悉這種提法逞力。具體地說糠爬,當我提到“緩存段”的時候,我就是指一段和緩存大小對齊的內(nèi)存揩抡,不關(guān)心里面的內(nèi)容是否真正被緩存進去(就是說保存在任何級別的緩存中)了殴玛。

當CPU看到一條讀內(nèi)存的指令時添祸,它會把內(nèi)存地址傳遞給一級數(shù)據(jù)緩存(或可戲稱為L1D$,因為英語中“緩存(cache)”和“現(xiàn)金(cash)”的發(fā)音相同)凡壤。一級數(shù)據(jù)緩存會檢查它是否有這個內(nèi)存地址對應(yīng)的緩存段耙替。如果沒有,它會把整個緩存段從內(nèi)存(從更高一級的緩存硝烂,如果有的話)中加載進來铜幽。是的,一次加載整個緩存段除抛,這是基于這樣一個假設(shè):內(nèi)存訪問傾向于本地化(localized),如果我們當前需要某個地址的數(shù)據(jù)橄教,那么很可能我們馬上要訪問它的鄰近地址喘漏。一旦緩存段被加載到緩存中,讀指令就可以正常進行讀取持灰。

如果我們只處理讀操作帽馋,那么事情會很簡單比吭,因為所有級別的緩存都遵守以下規(guī)律姨涡,我稱之為:

基本定律

在任意時刻,任意級別緩存中的緩存段的內(nèi)容赏表,等同于它對應(yīng)的內(nèi)存中的內(nèi)容匈仗。

一旦我們允許寫操作,事情就變得復(fù)雜一點了间狂。這里有兩種基本的寫模式:直寫(write-through)和回寫(write-back)火架。

  • 直寫:我們透過本級緩存,直接把數(shù)據(jù)寫到下一級緩存(或直接到內(nèi)存)中纺弊,如果對應(yīng)的段被緩存了骡男,我們同時更新緩存中的內(nèi)容(甚至直接丟棄),就這么簡單犹菱。這也遵守前面的定律:緩存中的段永遠和它對應(yīng)的內(nèi)存內(nèi)容匹配骚亿。

  • 回寫就有點復(fù)雜了。緩存不會立即把寫操作傳遞到下一級虑椎,而是僅修改本級緩存中的數(shù)據(jù)俱笛,并且把對應(yīng)的緩存段標記為“臟”段。(相當于異步)臟段會觸發(fā)回寫迎膜,也就是把里面的內(nèi)容寫到對應(yīng)的內(nèi)存或下一級緩存中】慕觯回寫后簸呈,臟段又變“干凈”了店茶。當一個臟段被丟棄的時候贩幻,總是先要進行一次回寫〈猿回寫所遵循的規(guī)律有點不同。

回寫定律

當所有的臟段被回寫后仿荆,任意級別緩存中的緩存段的內(nèi)容喧务,等同于它對應(yīng)的內(nèi)存中的內(nèi)容枉圃。

換句話說,回寫模式的定律中坎穿,我們?nèi)サ袅恕霸谌我鈺r刻”這個修飾語返劲,代之以弱化一點的條件:要么緩存段的內(nèi)容和內(nèi)存一致(如果緩存段是干凈的話),要么緩存段中的內(nèi)容最終要回寫到內(nèi)存中(對于臟緩存段來說)孵延。

直接模式更簡單亲配,但是回寫模式有它的優(yōu)勢:它能過濾掉對同一地址的反復(fù)寫操作,并且犬钢,如果大多數(shù)緩存段都在回寫模式下工作思灰,那么系統(tǒng)經(jīng)常可以一下子寫一大片內(nèi)存歹颓,而不是分成小塊來寫,前者的效率更高愿伴。

有些(大多數(shù)是比較老的)CPU只使用直寫模式电湘,有些只使用回寫模式,還有一些怎诫,一級緩存使用直寫而二級緩存使用回寫贷痪。這樣做雖然在一級和二級緩存之間產(chǎn)生了不必要的數(shù)據(jù)流量,但二級緩存和更低級緩存或內(nèi)存之間依然保留了回寫的優(yōu)勢劫拢。我想說的是舱沧,這里涉及到一系列的取舍問題,且不同的設(shè)計有不同的解決方案熟吏。沒有人規(guī)定各級緩存的大小必須一致。舉個例子悍引,我們會看到有CPU的一級緩存是32字節(jié)帽氓,而二級緩存卻有128字節(jié)

在直寫模式下黎休,這是很直接的,因為寫操作一旦發(fā)生镊逝,它的效果馬上會被“公布”出去嫉鲸。但是如果混著回寫模式,就有問題了座菠。因為有可能在寫指令執(zhí)行過后很久,數(shù)據(jù)才會被真正回寫到物理內(nèi)存中——在這段時間內(nèi)拓萌,其他處理器的緩存也可能會傻乎乎地去寫同一塊內(nèi)存地址升略,導(dǎo)致沖突。在回寫模型中炕倘,簡單把內(nèi)存寫操作的信息廣播給其他處理器是不夠的翰撑,我們需要做的是,在修改本地緩存之前涨醋,就要告知其他處理器逝撬。搞懂了細節(jié),就找到了處理回寫模式這個問題的最簡單方案靠闭,我們通常叫做MESI協(xié)議(譯者注:MESI是Modified坎炼、Exclusive拦键、Shared、Invalid的首字母縮寫萄金,代表四種緩存狀態(tài)媚朦,下面的譯文中可能會以單個字母指代相應(yīng)的狀態(tài))。

緩存一致性

緩存一致性協(xié)議就是要使多組緩存的內(nèi)容保持一致孙乖。

緩存一致性協(xié)議有多種,但是你日常處理的大多數(shù)計算機設(shè)備使用的都屬于“窺探(snooping)”協(xié)議弯屈,這也是我這里要講的恋拷。(還有一種叫“基于目錄的(directory-based)”協(xié)議蔬顾,這種協(xié)議的延遲性較大,但是在擁有很多個處理器的系統(tǒng)中酪我,它有更好的可擴展性且叁。)

“窺探”背后的基本思想是,所有內(nèi)存?zhèn)鬏敹及l(fā)生在一條共享的總線上逞带,而所有的處理器都能看到這條總線:緩存本身是獨立的,但是內(nèi)存是共享資源展氓,所有的內(nèi)存訪問都要經(jīng)過仲裁(arbitrate):同一個指令周期中遇汞,只有一個緩存可以讀寫內(nèi)存。

窺探協(xié)議的思想是络它,緩存不僅僅在做內(nèi)存?zhèn)鬏數(shù)臅r候才和總線打交道歪赢,而是不停地在窺探總線上發(fā)生的數(shù)據(jù)交換,跟蹤其他緩存在做什么点楼。所以當一個緩存代表它所屬的處理器去讀寫內(nèi)存時白对,其他處理器都會得到通知,它們以此來使自己的緩存保持同步蟀瞧。

只要某個處理器一寫內(nèi)存,其他處理器馬上就知道這塊內(nèi)存在它們自己的緩存中對應(yīng)的段已經(jīng)失效兆览。

為了簡化問題塞关,我省略了一些內(nèi)容:緩存關(guān)聯(lián)性(cache associativity),緩存組(cache sets)小压,使用分配寫(write-allocate)還是非分配寫(上面我描述的直寫是和分配寫相結(jié)合的椰于,而回寫是和非分配寫相結(jié)合的),非對齊的訪問(unaligned access)蜻牢,基于虛擬地址的緩存偏陪。如果你感興趣笛谦,所有這些內(nèi)容都可以去查查資料,但我不準備在這里講了饥脑。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末恳邀,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子灶轰,更是在濱河造成了極大的恐慌谣沸,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件框往,死亡現(xiàn)場離奇詭異鳄抒,居然都是意外死亡,警方通過查閱死者的電腦和手機椰弊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瓤鼻,“玉大人秉版,你說我怎么就攤上這事茬祷∏寤溃” “怎么了?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長秸妥。 經(jīng)常有香客問我滚停,道長,這世上最難降的妖魔是什么粥惧? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任键畴,我火速辦了婚禮,結(jié)果婚禮上突雪,老公的妹妹穿的比我還像新娘起惕。我一直安慰自己,他們只是感情好咏删,可當我...
    茶點故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布惹想。 她就那樣靜靜地躺著,像睡著了一般督函。 火紅的嫁衣襯著肌膚如雪嘀粱。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天辰狡,我揣著相機與錄音锋叨,去河邊找鬼。 笑死搓译,一個胖子當著我的面吹牛悲柱,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播些己,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼豌鸡,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了段标?” 一聲冷哼從身側(cè)響起涯冠,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎逼庞,沒想到半個月后蛇更,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡赛糟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年派任,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片璧南。...
    茶點故事閱讀 39,739評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡掌逛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出司倚,到底是詐尸還是另有隱情豆混,我是刑警寧澤篓像,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站皿伺,受9級特大地震影響员辩,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鸵鸥,卻給世界環(huán)境...
    茶點故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一奠滑、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧脂男,春花似錦养叛、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至汁讼,卻和暖如春淆攻,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背嘿架。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工瓶珊, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人耸彪。 一個月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓伞芹,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蝉娜。 傳聞我的和親對象是個殘疾皇子唱较,可洞房花燭夜當晚...
    茶點故事閱讀 44,647評論 2 354

推薦閱讀更多精彩內(nèi)容