深入理解緩存一致性協(xié)議MESI和MOESI
掃描二維碼
隨時隨地手機看文章
緩存一致性簡介
對于單核CPU來說,不存在數(shù)據(jù)一致性問題;然而對于多核系統(tǒng)來說,不同CPU上的cache和ram可能具有同一個數(shù)據(jù)的多個副本。這就會導(dǎo)致數(shù)據(jù)觀察者(CPU/GPU/DMA)能看到的數(shù)據(jù)不一致。
因此,維護cache一致性就非常有必要。維護cache一致性的關(guān)鍵是需要跟蹤每個Cache Line的狀態(tài),并且根據(jù)讀寫操作和總線上相應(yīng)的傳輸內(nèi)容來更新Cache Line在不同CPU核心上的Cache Hit狀態(tài)。
維護cache一致性有軟件和硬件兩種方式?,F(xiàn)在大多數(shù)處理器都采用硬件來維護。在處理器中通過cache一致性協(xié)議來實現(xiàn),這些協(xié)議維護了一個有限狀態(tài)機,根據(jù)存儲器讀寫指令/總線上的傳輸內(nèi)容,進行狀態(tài)遷移/相應(yīng)的cache操作來維護cache一致性。
cache一致性協(xié)議本質(zhì)上是如果通過硬件鎖定cache line的協(xié)議,以cache line為粒度,提高效率。
MESI協(xié)議
MESI協(xié)議(Write-Once總線監(jiān)聽協(xié)議),MESI這四個字母分別代表Modify、Exclusive、Shared和Invalid。Cache Line的狀態(tài)必須是這四個中的一種。前三種狀態(tài)均是數(shù)據(jù)有效下的狀態(tài)。Cache Line有兩個標(biāo)志-臟(dirty)和有效(valid)。臟代表該數(shù)據(jù)和內(nèi)存不一致。只有干凈的數(shù)據(jù)才能被多個Cache Line共享。
MESI狀態(tài)描述如下:
| 狀態(tài) | 描述 | 監(jiān)聽任務(wù) |
| M 修改(Modify) | 該緩存行有效,數(shù)據(jù)被修改了,和內(nèi)存中的數(shù)據(jù)不一致,該數(shù)據(jù)只存在于本緩存行中 | 緩存行必須時刻監(jiān)聽所有試圖讀該緩存行相對應(yīng)的內(nèi)存的操作,其他緩存須在本緩存行寫回內(nèi)存并將狀態(tài)置為E之后才能操作該緩存行對應(yīng)的內(nèi)存數(shù)據(jù) |
| E 獨享、互斥(Exclusive) | 該緩存行有效,數(shù)據(jù)和內(nèi)存中的數(shù)據(jù)一致,該數(shù)據(jù)只存在于本緩存行中 | 緩存行必須監(jiān)聽其他緩存讀主內(nèi)存中該緩存行相對應(yīng)的內(nèi)存的操作,一旦有這種操作,該緩存行需要變成S狀態(tài) |
| S 共享(Shared) | 該緩存行有效,數(shù)據(jù)和內(nèi)存中的數(shù)據(jù)一致,數(shù)據(jù)同時存在于其他緩存中 | 緩存行必須監(jiān)聽其他緩存是該緩存行無效或者獨享該緩存行的請求,并將該緩存行置為I狀態(tài) |
| I 無效(Invalid) | 該緩存行數(shù)據(jù)無效 | 無 |
對一條cache line的操作有如下幾種:
| 操作類型 | 描述 |
| 本地讀(local read) | 本地CPU讀取Cache Line |
| 本地寫(local write) | 本地CPU更新Cache Line |
| 遠(yuǎn)程讀(Remote read) | 來自其他cpu的讀cache信號 |
| 遠(yuǎn)程寫(Remote write) | 來自其他cpu的寫cache信號 |
MESI狀態(tài)及變化
M狀態(tài)跳變
如果cache line當(dāng)前狀態(tài)為M,那么下一個狀態(tài)有以下幾種情況:
|
當(dāng)前狀態(tài) |
操作 |
行為 |
下一個狀態(tài) |
|
M |
本地讀(local read) |
從該cache line中讀數(shù)據(jù),狀態(tài)不變 |
M |
|
M |
本地寫(local write) |
往該cache line中寫數(shù)據(jù),狀態(tài)不變 |
M |
|
M |
遠(yuǎn)程讀(Remote read) |
如果有其他cpu來讀該cache line必須完成如下操作:
|
S |
|
M |
遠(yuǎn)程寫(Remote write) |
如果有其他cpu來寫該cache line必須完成如下操作:
|
I |
E狀態(tài)跳變
如果cache line當(dāng)前狀態(tài)為E,那么下一個狀態(tài)有以下幾種情況:
|
當(dāng)前狀態(tài) |
操作 |
行為 |
下一個狀態(tài) |
|
E |
本地讀(local read) |
從該cache line中讀數(shù)據(jù),狀態(tài)不變 |
E |
|
E |
本地寫(local write) |
往該cache line中寫數(shù)據(jù),狀態(tài)改變成修改過:M |
M |
|
E |
遠(yuǎn)程讀(Remote read) |
如果有其他cpu來讀該cache line必須完成如下操作:
|
S |
|
E |
遠(yuǎn)程寫(Remote write) |
如果有其他cpu來寫該cache line必須完成如下操作:
|
I |
S狀態(tài)跳變
如果cache line當(dāng)前狀態(tài)為S,那么下一個狀態(tài)有以下幾種情況:
|
當(dāng)前狀態(tài) |
操作 |
行為 |
下一個狀態(tài) |
|
S |
本地讀(local read) |
從該cache line中讀數(shù)據(jù),狀態(tài)不變 |
S |
|
S |
本地寫(local write) |
往該cache line中寫數(shù)據(jù),狀態(tài)修改為M; 其他擁有該cache line備份的cpu的cache都必須置為無效狀態(tài)I |
M |
|
S |
遠(yuǎn)程讀(Remote read) |
如果有其他cpu來讀該cache line必須完成如下操作:
|
S |
|
S |
遠(yuǎn)程寫(Remote write) |
如果有其他cpu來寫該cache line必須完成如下操作:
|
I |
I狀態(tài)跳變
如果cache line當(dāng)前狀態(tài)為S,那么下一個狀態(tài)有以下幾種情況:
|
當(dāng)前狀態(tài) |
操作 |
行為 |
下一個狀態(tài) |
|
I |
本地讀(local read) |
從內(nèi)存中讀cache line,存在三種情況:
|
S或E |
|
I |
本地寫(local write) |
從內(nèi)存中讀cache line,然后修改該cache line,狀態(tài)修改為M; 如果其他cpu存在該cache line的備份,那么這些備份必須修改為無效I; |
M |
|
I |
遠(yuǎn)程讀(Remote read) |
本地cache為無效狀態(tài),其他cpu讀不影響本地狀態(tài); |
I |
|
I |
遠(yuǎn)程寫(Remote write) |
本地cache為無效狀態(tài),其他cpu讀不影響本地狀態(tài); |
I |
MESI狀態(tài)機
MESI協(xié)議多個狀態(tài)的最終狀態(tài)機如下:
MESI協(xié)議的缺點
如果由特定塊上的各種高速緩存執(zhí)行連續(xù)讀取和寫入操作,則每次都必須將數(shù)據(jù)刷新到總線上。因此,主存儲器將在每次沖洗時拉動它并保持清潔狀態(tài)。但這不是一項要求,只是由于MESI的實施而導(dǎo)致的額外開銷。MOESI協(xié)議克服了這一挑戰(zhàn)。
MOESI協(xié)議
MOESI協(xié)議引入了一個O(Owned)狀態(tài),并在MESI協(xié)議的基礎(chǔ)上,進行了重新定義了S狀態(tài),而E、M和I狀態(tài)和MESI協(xié)議的對應(yīng)狀態(tài)相同。
-
O位。O位為1表示在當(dāng)前Cache 行中包含的數(shù)據(jù)是當(dāng)前處理器系統(tǒng)最新的數(shù)據(jù)拷貝,而且在其他CPU中一定具有該Cache行的副本,其他CPU的Cache行狀態(tài)為S。如果主存儲器的數(shù)據(jù)在多個CPU的Cache中都具有副本時,有且僅有一個CPU的Cache行狀態(tài)為O,其他CPU的Cache行狀態(tài)只能為S。與MESI協(xié)議中的S狀態(tài)不同,狀態(tài)為O的Cache行中的數(shù)據(jù)與存儲器中的數(shù)據(jù)并不一致。
-
S位。在MOESI協(xié)議中,S狀態(tài)的定義發(fā)生了細(xì)微的變化。當(dāng)一個Cache行狀態(tài)為S時,其包含的數(shù)據(jù)并不一定與存儲器一致。如果在其他CPU的Cache中不存在狀態(tài)為O的副本時,該Cache行中的數(shù)據(jù)與存儲器一致;如果在其他CPU的Cache中存在狀態(tài)為O的副本時,Cache行中的數(shù)據(jù)與存儲器不一致。
MOESI協(xié)議優(yōu)點
MOESI協(xié)議是MESI協(xié)議的一個更復(fù)雜的版本,它避免了當(dāng)另一個處理器嘗試讀取時,需要將臟緩存行(dirty cache line)寫回主內(nèi)存的情況。相反,Owned狀態(tài)允許處理器直接向其他處理器提供修改后的數(shù)據(jù)。當(dāng)兩個CPU之間的通信延遲和帶寬顯著優(yōu)于主內(nèi)存時,這種方式是有益的。一個例子是具有每核L2緩存的多核CPU。
盡管MOESI協(xié)議能夠快速地從緩存中共享臟緩存行,但它不能快速共享干凈的緩存行。如果一個緩存行相對于內(nèi)存是干凈的并且處于共享狀態(tài),那么對該緩存行的任何監(jiān)聽請求都將從內(nèi)存中填充,而不是從緩存中。
如果處理器希望寫入一個Owned緩存行,它必須通知其他正在共享該緩存行的處理器。根據(jù)具體實現(xiàn),它可能只是告訴它們使它們的副本失效(將其自己的副本移動到Modified狀態(tài)),或者它可能告訴它們用新內(nèi)容更新它們的副本(保留其自己的副本在Owned狀態(tài))。
MOESI協(xié)議相比于MESI協(xié)議的優(yōu)點是,當(dāng)在其他CPU cache中發(fā)生Read hit時候,不需要將數(shù)據(jù)寫回存儲器,而是將數(shù)據(jù)從一個CPU直接傳到另一個CPU,提高了cache利用率。
MOESI具體狀態(tài)跳變這里就不重復(fù)的推演了,有興趣的可以自己試一下。
ACE 是按照MOESI協(xié)議來實現(xiàn)的。
后記
技術(shù)很重要,技術(shù)背后的思想更重要!
技術(shù)背后的某些思想就是你解決以后問題的鑰匙。我的文章可能一篇中知識點不太多,但是力求讓你能深入理解,為你進階打下基礎(chǔ)。如果有一點點收獲,也算是我對中國芯片行業(yè)的一點點貢獻吧。





