內存一致性模型

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!安全

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

1.coherence肯定了讀取操做可能返回什麼值;jsp

2.consistency肯定了寫入值何時讀取操做返回。性能

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

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

Memory consistency modelthis

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

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

相關文章
相關標籤/搜索