監聽協定(snooping protocol)
再想像我們那群編輯,但現在他們全圍著一張桌子坐,並大聲喊出自己的動作:「我要改第三句了!」桌邊每個人都聽見,握有那一頁的人就把自己現在已錯的副本撕掉。沒有人保管一份「誰有什麼」的主清單——協調靠的是大家都聽一個共享頻道。監聽協定(snooping protocol)正是這樣運作:每個快取都盯著(監聽)一條廣播記憶體活動的共享匯流排,一聽到自己握有的列就反應。
機制上,所有快取都接到一個共享的廣播媒介——典型上是一條匯流排。當一個核心想寫一條共享列時,它就在匯流排上廣播這個意圖。其他每個快取都不停地監聽匯流排,於是各自檢查是否握有那條列;若有,在寫入失效(write-invalidate)方案下就使(丟棄)自己的副本失效,在寫入更新(write-update)下就更新它。讀取也類似:讀取未命中會被廣播,握有最新副本的快取可以供應它。因為廣播傳到每個人,匯流排上操作的順序自然就把寫入序列化了,從而給出一致性。
監聽對小型系統既簡單又快,正是因為聽眾少時廣播很便宜——這就是為什麼它在單一晶片那少數幾個核心裡很常見。但廣播在大規模時是它的敗筆:每一次一致性動作都送到每一個快取,於是共享匯流排飽和,監聽流量隨核心數成長。超過二、三十個核心後,向所有人廣播就太貴了,系統便改用目錄協定(directory protocol),只對真正共享某條列的快取傳訊息。
核心 A、B、C 都快取了列 L。核心 A 想寫 L,於是在匯流排上廣播「使 L 失效」。B 和 C 正在監聽,看到廣播,就丟掉自己對 L 的副本。現在 A 是唯一持有者,可以自由寫入。當 B 之後讀取 L 時,它的讀取未命中被廣播,由 A 供應更新後的列。
每個快取都偷聽共享匯流排;一次廣播的「失效」讓所有其他持有者丟掉副本——簡單,但在大規模時會氾濫。
監聽需要一個傳到每個快取的廣播媒介,所以它的一致性流量隨核心數成長。它對少數幾個核心擴展得好、對許多核心擴展得差——那道擴展之牆,正是目錄協定存在的原因。