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





