1 CPU Cache 結構緩存

CPU 在執行指令的時候須要從 memory 中獲取指令和須要的數據,可是 CPU 的速度要比 memory 快不少,這就致使了 CPU 大部分時間都不是在作運算上而是用在了和 memory 進行數據的 I/O 過程當中,這樣性能是很低的。這就致使了 CPU cache 的產生,CPU 將數據從 memory 讀取到 cache 中,在 cache 中對數據進行讀寫的速度是很快的,這樣就提升了性能。CPU 執行運算時不可能須要某一個數據就去讀取一次,這樣就增長了 I/O 的頻率,致使性能低下。因此會一次性讀取一塊內存的數據存放到 cache 中, 這個塊稱爲 「cache line」 , cache line 的大小是固定的, 一般是 2 的 N 次方,在 16 ~ 256 byte 不等。當某個數據首次被 CPU 訪問時, cache 中不存在,這稱爲 「cache miss」 (或 「startup」 或 「warmup」 cache miss)。這意味着 CPU 必需要去 memory 中讀取該數據,這時候 CPU 必須等待(stalled)。當 cache 裝滿後,後續的 cache miss 須要置換 cache 中現有的數據,這樣的 cache miss 被稱爲 「capacity miss」 。若是隨後又訪問了被替換的 cache line ,這時的 cache miss 被稱爲 「associativity miss」 。 安全
當 CPU 寫數據的時候,須要保證該數據在多個 CPU cache 之間的一致性。在寫以前必須先讓其餘 CPU cache 中的該數據失效,以後才能夠安全的寫數據。若是這個數據已經存在於要執行寫指令的 CPU cache 中,可是是 read only 的,這個過程被稱爲 "write miss" ,一旦其餘 CPU cache 中的該數據都失效後,該 CPU 能夠不斷的寫或讀其 cache 中的數據。若是另外某一個 CPU 嘗試訪問該數據,會造成一次 cache miss ,這時稱爲 「communication miss」 。由於這一般是多個 CPU 之間使用緩存通訊形成的。性能
2. 緩存一致性協議spa
緩存一致性協議用於管理多個 CPU cache 之間數據的一致性,這些協議十分複雜,在這裏咱們僅討論 MESI 協議的四種狀態。blog
M : modified內存
E : exclusiveci
S : sharedrem
I : invalidit
協議在每個 cache line 中維護一個兩位的狀態 「tag」 ,這個 「tag」 在 cache line 的物理地址或者數據後。io
modified 狀態的 cache line 是因爲相應的 CPU 進行了寫操做,同時也表示該數據不會存在於其餘 CPU 的 cache 中。也就說明這個最新的數據目前是被執行寫操做的 CPU cache line 獨佔的。由於如此當前 cache 須要對該數據負責,好比將該數據傳遞給其餘 CPU cache ,或者是將該數據寫回到 memory 中。而這些操做都須要在 reuse cache line (置換)以前完成。
exclusive 狀態和 modified 狀態相似,區別是 CPU 尚未修改 cache line 中的數據。在 exclusive 狀態下 CPU 能夠不通知其餘 CPU 而直接 cache line 進行操做。也就是說 exclusive狀態是該 CPU 對這個數據的獨佔。此時因爲 memory 中和 cache line 中的數據都是最新的,因此不須要對 exclusive 狀態的 cache line 執行寫回 memory 的操做就能夠直接 reuse。
shared 狀態的 cache line ,其數據可能在一個或者是多個 CPU cache 中,此時 CPU 不能直接修改 cache line 中的數據,而是須要先通知其餘 CPU cache 。和 exclusive 同樣, shared 狀態的 cache line 對應的 memory 中的數據也是最新的,所以也能夠直接 reuse cache line。
invalid 狀態時 cache line 是空的。當新的數據要進入 cache 的時候優先選擇 invalid 的 cache line ,之因此如此是由於若是選中其餘狀態的 cache line 會涉及到 cache line 中數據的置換 , 而以後若是這個被替換的數據被訪問到會形成 cache miss ,這樣形成很大的開銷。



3 MESI 協議消息
- Read。"read" 消息用來獲取指定物理地址上的 cache line 數據。
- Read Response。該消息攜帶了 「read」 消息所請求的數據。read response 可能來自於 memory 或者是其餘 CPU cache。
- Invalidate。該消息將其餘 CPU cache 中指定的數據設置爲失效。該消息攜帶物理地址,其餘 CPU cache 在收到該消息後,必須進行匹配,發如今本身的 cache line 中有該地址的數據,那麼就將其從 cahe line 中移除,並響應 Invalidate Acknowledge 迴應。
- Invalidate Acknowledge。該消息用作迴應 Invalidate 消息。
- Read Invalidate。該消息中帶有物理地址,用來講明想要讀取哪個 cache line 中的數據。這個消息還有 Invalidate 消息的效果。其實該消息是 read + Invalidate 消息的組合,發送該消息後 cache 指望收到一個 read response 消息。
- Writeback。 該消息帶有地址和數據,該消息用在 modified 狀態的 cache line 被置換時發出,用來將最新的數據寫回 memory 或其餘下一級 cache 中。
4 MESI狀態圖

根據 MESI 協議消息的發送和接收或者是對數據的讀寫,cache line 的狀態會在 modified , exclusive , shared , invalid 之間進行轉換。
- cache 經過 writeback 將數據回寫到 memory 或者下一級 cache 中。這時候狀態由 modified 變成了 exclusive 。
- cpu 直接將數據寫入 cache line ,致使狀態變爲了 modified 。
- CPU 收到一個 read invalidate 消息,此時 CPU 必須將對應 cache line 設置成 invalid 狀態 , 而且響應一個 read response 消息和 invalidate acknowledge 消息。
- CPU 須要執行一個原子的 readmodify-write 操做,而且其 cache 中沒有緩存數據。這時候 CPU 就會在總線上發送一個 read invalidate 消息來請求數據,並試圖獨佔該數據。CPU 能夠經過收到的 read response 消息獲取到數據,並等待全部的 invalidate acknowledge 消息,而後將狀態設置爲 modifie 。
- CPU須要執行一個原子的readmodify-write操做,而且其local cache中有read only的緩存數據(cacheline處於shared狀態),這時候,CPU就會在總線上發送一個invalidate請求其餘cpu清空本身的local copy,以便完成其獨自霸佔對該數據的全部權的夢想。一樣的,該cpu必須收集全部其餘cpu發來的invalidate acknowledge以後才能更改狀態爲 modified。
- 在本cpu獨自享受獨佔數據的時候,其餘的cpu發起read請求,但願獲取數據,這時候,本cpu必須以其local cacheline的數據迴應,並以read response迴應以前總線上的read請求。這時候,本cpu失去了獨佔權,該cacheline狀態從Modified狀態變成shared狀態(有可能也會進行寫回的動做)。
- 這個遷移和f相似,只不過開始cacheline的狀態是exclusive,cacheline和memory的數據都是最新的,不存在寫回的問題。總線上的操做也是在收到read請求以後,以read response迴應。
- 若是cpu認爲本身很快就會啓動對處於shared狀態的cacheline進行write操做,所以想提早先霸佔上該數據。所以,該cpu會發送invalidate敦促其餘cpu清空本身的local copy,當收到所有其餘cpu的invalidate acknowledge以後,transaction完成,本cpu上對應的cacheline從shared狀態切換exclusive狀態。還有另一種方法也能夠完成這個狀態切換:當全部其餘的cpu對其local copy的cacheline進行寫回操做,同時將cacheline中的數據設爲無效(主要是爲了爲新的數據騰些地方),這時候,本cpu不勞而獲,直接得到了對該數據的獨佔權。
- 其餘的CPU進行一個原子的read-modify-write操做,可是,數據在本cpu的cacheline中,所以,其餘的那個CPU會發送read invalidate,請求對該數據以及獨佔權。本cpu回送read response」和「invalidate acknowledge」,一方面把數據轉移到其餘cpu的cache中,另一方面,清空本身的cacheline。
- cpu想要進行write的操做可是數據不在local cache中,所以,該cpu首先發送了read invalidate啓動了一次總線transaction。在收到read response迴應拿到數據,而且收集全部其餘cpu發來的invalidate acknowledge以後(確保其餘cpu沒有local copy),完成整個bus transaction。當write操做完成以後,該cacheline的狀態會從Exclusive狀態遷移到Modified狀態。
- 本CPU執行讀操做,發現local cache沒有數據,所以經過read發起一次bus transaction,來自其餘的cpu local cache或者memory會經過read response迴應,從而將該 cache line 從Invalid狀態遷移到shared狀態。
- 當cache line處於shared狀態的時候,說明在多個cpu的local cache中存在副本,所以,這些cacheline中的數據都是read only的,一旦其中一個cpu想要執行數據寫入的動做,必須先經過invalidate獲取該數據的獨佔權,而其餘的CPU會以invalidate acknowledge迴應,清空數據並將其cacheline從shared狀態修改爲invalid狀態。
