程式設計師的 CPU 微架構

快取一致性協定(MESI)

/ MESI -> MESS-ee /

每個核心都有自己的 L1(且常有 L2)快取,所以同一個記憶體位址可能同時被複製進好幾個快取裡。現在想像四個人各自握著同一份試算表的影印本:其中一人一改某格,其他每一份影本就悄悄地錯了。快取一致性協定就是防止這件事的帳務工作——它保證沒有任何核心會在另一核心改動某列之後,還讀到那一列的過時副本。MESI 是達成此事的經典協定,它的名字正是一個被快取的列所能處於的四種狀態。

每個快取裡的每一列都帶著 MESI 四種狀態之一。Modified(M,已修改):本核心擁有唯一的副本且它已被改動(髒);記憶體是過時的,本核心必須在別人能讀它之前先寫回。Exclusive(E,獨佔):本核心擁有唯一副本且它與記憶體相符(乾淨);它可以被悄悄寫入並轉為 M,無需通知其他核心。Shared(S,共享):本核心持有一份乾淨副本,其他核心也可能持有乾淨副本;讀取免費,但寫入前必須先把其他份作廢。Invalid(I,無效):這個項目是空的或已過時,必須重新抓取。各核心透過互連匯流排交談:當某核心想寫一個其他核心以 S 持有的列時,它廣播一個作廢(invalidate)訊息並等待對方把副本降為 I——之後它才能把該列移到 M 並寫入。讀取另一核心以 M 持有的列,會迫使那個核心寫回並降級。變體微調了這套:MESIF 多了一個 Forward 狀態(指定一個共享者來回應請求),MOESI 多了一個 Owned 狀態(一個髒的列可以被共享而不必先寫回記憶體)。

這個協定是每個並行程式設計師遲早會遇到的兩種代價背後的隱藏機制。偽共享之所以昂貴,正是因為兩個核心寫同一個共享的列,會讓那一列在它們的 M 狀態之間不斷彈跳、彼此作廢——即使它們碰的是不同的位元組。而一個原子讀改寫,按定義必須以類獨佔的狀態取得那一列,好讓沒有其他核心能交錯插入,這正是為何「無競爭的原子操作」便宜、而「高度競爭的原子操作」會在一致性流量上序列化的原因。一致性是自動且正確的,但它並不免費。

兩個核心上的兩個執行緒,各自遞增住在同一個 64 位元組列裡的計數器。核心 0 寫入 → 它的列變 M、核心 1 的副本變 I。核心 1 寫入 → 它必須重新抓取、核心 0 的變 I。這個列每次迭代都在互連匯流排上來回彈跳:光是一致性流量就帶來百倍的拖慢。

透過 MESI 看見的偽共享機制:一個看起來乾淨的迴圈,被「作廢再重抓」給序列化了。

一致性會自動讓各快取保持一致——它和語言記憶體模型的順序保證並不是同一回事。一致性關心的是單一位置的各份副本;跨不同位置的可見性與順序仍需原子操作與屏障。

又称
cache coherence protocolMESIFMOESI快取一致性協定