內存一致性模型


Cache coherence

  本文主要討論的是內存一致性問題(memory consistency),和緩存一致性(cache coherence)是不同的。在《計算機體系結構:量化方法研究》第五章中,memory consistency是由cache coherence引出的,所以我們就先來說說cache coherence吧。考慮下圖:

如圖,A和B讀取X到緩存后,A直寫(write through)X的值為0,但此時B緩存中存儲的X的值仍然是1。即如果此時B讀取X,將會收到數值1!

通俗地說,如果在每次讀取某一數據項時都會返回該數據項的最新寫入值,則稱這個存儲系統是一致的。這一定義有些含糊和簡單,卻包含了兩個關鍵的方面:

1.coherence確定了讀取操作可能返回什么值;

2.consistency確定了寫入值什么時候讀取操作返回。

簡單來說,coherence其實保證的就是對某一個地址的讀操作返回的值一定是那個地址的最新值(注意coherence和consistency最大的區別就是是對某一個地址還是全局),而這個最新值可能是該線程所處的CPU核心剛剛寫進去的那個最新值,也可能是另一個CPU核心上的線程剛剛寫進去的最新值。具體嚴謹的定義我直接從書上截圖好了:

這三個條件只是保證了coherence,還未考慮consistency的問題。比如,如果一個處理器對X的寫入操作僅比另一個處理器對X的讀取操作提前很短的一點時間,那就不可能確保該讀取操作會返回這個寫入值。這個寫入值多久后能確保被讀取操作讀取到,這正是memory consistency討論的問題。

Memory consistency model

  這部分我主要參考的是《Shared Memory Consistency Models:A Tutorial》這篇文章。先說一下最簡單的順序一致性(Sequential consistency)。定義如下:

Definition: [A multiprocessor system is sequentially consistent if] the result of any execution is
the same as if the operations of all the processors were executed in some sequential order, and the
operations of each individual processor appear in this sequence in the order specified by its program.

這個定義包含兩個方面:1.在每個處理器內,維護程序次序;

           2.在所有處理器間維護一個單一的操作次序,即所有處理器看到的操作次序要一樣。這就使內存操作需要有原子性(或瞬發性)。

  

圖 a 闡述了 SC 對程序次序的要求(要求一)。當處理器 P1 想要進入臨界區時,
它先將 Flag1 更新為 1, 再去判斷 P2 是否嘗試進入臨界區(Flag2). 若 Flag2 為 0,
表示 P2 未嘗試進入臨界區,此時 P1 可以安全進入臨界區。這個算法假設如果 P1 中讀到 Flag2 等於0, 那么P1的寫操作(Flag1=1)會在P2
的寫操作和讀操作之前發生,這可以避免 P2 也進入臨界區。SC 通過維護程序次序來保證這一點。

圖 b 闡述了原子性要求。原子性允許我們假設 P1 對 A 的寫操作對整個系統(P2, P3) 是同時可見的:P1 將 A 寫成1; P2 先看到 P1 寫 A 后才寫 B;P3 看到 P2 寫 B 后才去讀 A, P3 此時讀出的 A 必須要是 1 (而不會是0)因為從 P2 看來操作執行次序為 (A=1)->(B=1), 不允許P3在看到操作 B=1 時,沒有看到 A=1.

實現SC需要付出代價,使性能降低,同時也會限制編譯器的優化。為了獲得更好的性能,引入寬松內存一致性模型(relaxed memory consistency models).

根據《量化》一書,relaxed memory consistency models有多種模型,比如放松W->R;放松W->W;放松 R->W 和 R->R,這包括多種模型,其中Release consistency我們單獨拿出來說。

Release consistency

 Release consistency包含兩個同步操作,acquire和release。

1)  ACQUIRE:  對於所有其它參與者來說, 在此操作后的所有讀寫操作必然發生在ACQUIRE這個動作之后。

2)  RELEASE:  對於所有其它參與者來說, 在此操作前的所有讀寫操作必然發生在RELEASE這個動作之前。

注意, 這其中任意一個操作, 都只保證了一半的順序:
對於ACQUIRE來說, 並沒保證ACQUIRE前的讀寫操作不會發生在ACQUIRE動作之后.
對於RELEASE來說, 並沒保證RELEASE后的讀寫操作不會發生在RELEASE動作之前.

因此release和acquire的組合形成了內存屏障。舉個例子

處理器A執行以下代碼:

a.store(3);
b.store(4);
m.store(5, release);

處理器B執行以下代碼:

m.load(acquire);
g.load();
h.load();

release和acquire組成的內存屏障保證了當線程 B 執行完m.load(acquire);之后, 線程 B 必須已經能看到a==3,b==4,且g和h的load操作不會發生在處理器A的release操作之前。

 

參考鏈接:Shared Memory Consistency Models:A Tutorial

     http://zhihu.com/question/24301047/answer/83422523


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM