Cache中的MESI協議基本知識介紹

Rings發表於2016-10-13
  • Cache相關概念解釋

#0. 前言背景.

本文為本人在閱讀由E. McKenney所著《Memory Barriers : a Hardware View For Software Hackers》一文的讀書筆記 。本文首先介紹了關於cache 一些基本概念。接下來,介紹了cache 一致性協議:MESI (Modified, Exclusive, Shared, Invalidate)。在詳細討論了各個狀態之間的 轉換及觸發該轉換的條件後,作者詳細介紹了有其帶來的在SMP架構下所導致的問題並引入記憶體屏障 的概念並詳細介紹了記憶體屏障在實際使用過程中的所遇到的種種問題及解決方案。

#1. Cache一致性協議:MESI

由於CPU語句記憶體之間的訪問速度差,現今幾乎所有的架構下,為了提高系統的執行效率,我們都會引入 Cache來解決,由於CPU與記憶體訪問之間的速度差所帶來的問題。通常做普通的一顆CPU的執行速度就可以達到每納秒執行十多條指令,但是倘若從記憶體中讀取資料的話則需要少十幾納秒多則幾十納秒。 (1) 現有的當前架構如下:
cachearc-1
這裡我們將Cache模組畫在cpu方塊之外,只是為了描述方便,實際中,通常是將Cache系統整合在CPU中,形成所謂的L1 Cache以及L2 Cache或者 L3 Cache等。通常出我們常說的Cache為資料Cache,其主要的作用就是儲存CPU訪問過的資料,因為依據程式碼和資料的相鄰特性之前訪問過的指令和資料將會在不久的將來在次被訪問。當然隨著當前流水線技術的發展,CPU的多發射架構也越來越成為主流,因此處理上述資料Cache外,還存在著指令Cache,而指令Cache又進一步的提高了CPU的系統主頻。為了解決SMP架構下由於由於各個CPU Core所對應的Cache造成的Cache中資料的不一致,我們採用MESI 演算法來儲存資料的一致性。

smp-1-1

Cache miss: 當cpu所需要的資料未在Cache line中存在時,此時如果CPU訪問Cache查詢該資料時候,即發生 Cache Miss。 也稱作:Startup 或者 Warmup Miss。 Capacity Miss: 噹噹前的Cache Line中的資料已滿時 ,如果此時再次發生Cache Miss,則需要將現有的資料由當前的Cache Line中置換出,此時我們就稱:Capacity Miss。

MESI中M.E.S.I各自所代表的含有如下:

狀態 描述
M(Modified) 該行資料被修改,以和該資料在記憶體中的映像所不同。最新的資料只存在於Cache中
E(Exclusive) 該行資料有效,且資料與記憶體中的資料一致,但資料值只存在於本Cache中。通俗來說,該資料只在Cache中獨一份
S(Share) 該行資料有效,且該資料與記憶體中的資料一致。同時,該資料存在與其它多個Cache中
I(Invalid) 該行資料無效

mesi-1

各個狀態之間的轉換如下所示:

mesi_t-1

Read訊息:read訊息中包括了所需要讀取的cache line的實體地址。

Read相應訊息:該訊息中包含了 read訊息中所請求的資料。該資料有可能是由記憶體或者其它cpu中所獲得。例如:其它cpu中含有所需要的處於“modified”模式的資料。 cache必須回應一個read相應訊息。

invalidate訊息:invalidate訊息包含需要進行invalidate的cache line的實體地址。 所有的cache必須要將相應的資料從其cache和相應訊息中刪除。

invalidate應答:當一個cpu接受到一個invalidate訊息後,在其完成將相應的資料從其cache中刪除後必須給予相應的invalidate應答訊息。

read無效:其訊息中包含了所需要讀取的cache line的實體地址。於此同時,將其相直接關聯的cache中的資料刪除。 因此,其包含了read和invalidate兩重意思。 一個 read invalidate訊息需要:一個read相應以及一些列的 invalidate 應答作為其回應。

writeback: 該訊息中包含了需要寫回到記憶體的:地址和資料。該訊息允許cache強制將其cache line置位modified狀態,當其需要較為其它資料騰出相應的空間時。

下面我們就對上述的四種狀態給出一個直觀的介紹。

(0)初始狀態, 初始狀態如上述的圖二所示。

(1)shared狀態,該狀態下Cache Line中的資料與Memory中的資料一致,且其資料也存在於其它的CPU Cache Line中。
mesi_modified-1

(2)Modified狀態,在該狀態下Cache Line中的資料與Memory資料一致,但資料只是存在與本CPU的Cache Line中。

smp-1-1

下面我們就來介紹一下MESI轉換圖中的各個狀態並給出詳細的分析和介紹。

#2. MESI狀態轉換詳解.

  • a: 當一個cache line處於M狀態,表明該cache line中的資料,因此當將cache line中 的資料回寫到記憶體時候,就由M狀態變為 E,表明資料有效,且已經回寫到記憶體中, 但由於為及時的與其它cpu進行資料同步,故而只有在本cpu中存在著該資料。其中 藍色的點代表修改後的資料。

mesi_a-1

  • b: 當cpu想一個處於獨享狀態的cache line中寫入資料時候,由於該cache line處於 獨享狀態(其表明:該cache line中的資料只在本cpu的cache line中存在),因 此,當處於獨享狀態下時候,我們無需將資料做其他額外的工作,直接修改資料 即可。

mesi_b-1

  • c: 此種狀態下,由Modified到invalidate表明,將資料從相應的cache line中刪除。 將本地的資料刪除。即執行清空資料操作。即:轉換由類似於e的狀態,到初始 狀態0. 各個cpu在接收到read invalidate訊息後,各個cpu必須回覆read res和 invalidate ACk訊息。 傳送read invalidate訊息是通知所有cpu將其各自本地的 資料給清除掉,在完成本地資料的清除後,傳送一個invalidate ack訊息,告訴 發起read invalidate訊息的主cpu,其它cpu已經完成該項操作。
  • d: cpu對於一個未在cache line中的資料進行原子的讀寫操作。此時cache line會由 原來的invaldate 狀態,轉為Modified狀態。首先傳送一個read invalidate訊息 而後接收到 read相應訊息,而該訊息中包含有相應的包含所請求的資料。當cpu接收 完所有的 invalidate應答相應後,則完成本次的資料讀取。
  • e: cpu在一個已有資料的cache line上執行原子的讀寫操作,由於原資料已存在於 cache line中,因此如果對該cache line進行讀寫操作,首先要使得原有資料由 該cache line中刪除,因此傳送一個invalidate訊息。由於資料同樣也存在於其它 cpu的cache line中,因此必須等到所有的cpu均返回 invalidate 應答,方可以認 本次讀寫操作結束。

mesi_e-1

  • f: 當處於Modified狀態時候,一個其它cpu發起讀資料操作。此時,擁有資料的cpu需要 將該資料發生到其它cpu的cache line中並將資料更新到記憶體中。該中狀態轉換,通常是 由一個read訊息所發起,當該cpu接收到一個read訊息時候,那麼該cpu將回復一個read相應 且該相應訊息中包含著所請求的資料。
  • g: 當其他cpu需要從cache line中讀取資料時,其是通過其它cpu cache或者記憶體中 讀取相應的資料。無論何種情況,該cpu儲存了一份read-only拷貝。本次轉換由 cpu接收到一個read訊息後發起該請求read 請求。 該cpu收到該訊息後,會傳送 一個包含所請求資料的 read 響應訊息。
  • h: 當該cpu意識到不僅需要將某些資料寫入到該cpu的cache line中時候,其將會傳送一個invalidate訊息。cpu只有等到所有的cpu都已傳送invalidate ack訊息後,方可認為完成本次操作,否則的話會導致該cpu 無法知道其他cpu中的資料是否被刪除。或者,其他所有的cpu將該cache line從他們的caches中通過使用 writeback訊息將其從cache中刪除(為了未來可能的資料騰出空間)。因此,該cpu中的資料變為獨享資料。此時的狀態,cpu0,可以發生資料寫入操作,此時會傳送一個Invalidate訊息給其它所有的cpu,例如:cpu1,cpu1將其cache line中資料刪除,並返回invalidate ack訊息。 此時,由於其它的cpu中的資料均被刪除,故而cpu0中的資料為獨享狀態。

mesi_h-1

  • i: 當其它某些cpu試圖在由本cpu cache line中所擁有的資料上執行一個原子的讀寫操作時候。該 cpu將該資料從本cache line中刪除(使用 invalidate訊息)。該項轉移由該cpu接受到一個read invalidate訊息開始,以該cpu響應一個 read 響應訊息以及一個invalidate ack訊息。因為在mesi 協議中對於一個invalidate訊息必須要有一個invalidate ack訊息與之相應對於。最後的狀態回到(0) 狀態。
  • j: 當cpu儲存一個未在其cache line中的資料項時候,其會傳送一個read invalidate消 息給其它cpu,且該cpu等待,直到其接收一個 read響應訊息和所有cpu返回的invalidate ack訊息。該cache line將由(b)狀態轉為修改狀態,當完成實際的資料儲存後。
  • k: cpu讀取一個資料,而該資料並不在該cpu的cache line中。cpu將傳送一個read訊息 且當讀取到read 響應訊息後,完成本次操作。
  • l: 當某些cpu執行對在其cache line中的資料儲存命令時,但是該其cpu cache line中 的資料是read only狀態,因為該cache line中的資料是在其它cpu中,而該cpu cache line中的資料只是其它cpu cache line中的資料的一份拷貝。該次轉為由接收到一個invalidate訊息開始並返回一個invalidate ack訊息。

正是由於多核架構以及指令的亂序執行所帶來的資料在不同核直接的資料同步問題,需要我們在使用存在著這樣的一種現象:當我們使用記憶體中某個資料的時候,如果此時執行該指令的核中的資料Cache中的資料與記憶體中的資料一致的話,此時執行並無問題。但是當在後續的執行過程,由於亂序以及多核,此時該指令執行在另外的一個核之上,而該核中Cache的資料並同步,此時系統將取出舊資料進行執行。這樣便導致了程式執行出錯誤的結果,為了防止這該種情況的發生,在使用某個變數之前,強制的要求各個核進行資料的同步,當資料同步完成後,方可進行後續的執行。因此,引入了記憶體屏障的概念。當然為了效能的考慮,我們又將記憶體屏障細分為:讀寫兩種記憶體屏障操作。

相關文章