最簡單的高速緩存(左) 多級緩存(右)

數據的讀取和存儲都要經過高速緩存(Cache),CPU(CPU Core)與高速緩存間有一條特殊的快速通道。主存(Main Memory)與高速緩存都連接在系統匯流排(Bus)上,系統匯流排同時還用於其他組件的通信。

在高速緩存出現後不久,系統變得更加複雜,高速緩存與主存間的速度差異被拉大,直到加入了另一級緩存,新加入的緩存比第一級緩存更大的同時更慢。由於加大一級緩存的做法從經濟上考慮是行不通的,所以有了二級緩存,甚至現在的某些系統已經擁有了三級緩存。

CPU緩存出現的原因

CPU的頻率太快,快到主存跟不上,這樣在處理器時鐘週期內,CPU經常需要等待主存,浪費資源。所以緩存的出現,是為了緩解CPU和內存間速度的不匹配問題。(結論:CPU>緩存>主存)

CPU緩存的意義

1)時間局部性:如果某個數據被訪問,那麼在不久的將來它很有可能會被再次訪問。

2)空間局部性:如果某個數據被訪問,那麼與它相鄰的數據很快也能被訪問。

緩存一致性(MESI)

保證了每個緩存中使用的共享變數的副本是一致的。它核心的思想是:當CPU寫數據時,如果發現操作的變數是共享變數,即在其他CPU中也存在該變數的副本,會發出信號通知其他CPU將該變數的緩存行置為無效狀態,因此當其他CPU需要讀取這個變數時,發現自己緩存中緩存該變數的緩存行是無效的,那麼它就會從內存重新讀取。

Modified (被修改)

該緩存行只被緩存在該CPU的緩存中且是被修改過的,因此其與主存中的數據是不一致的。該緩存行的內存需要在未來的某個時間點寫回主存,這個時間點是允許其他CPU讀取主存中相應的內存之前,但該狀態的值被寫回主存後,該緩存行的狀態就會變成獨享狀態。

Exlusive(獨享)

該緩存行只被緩存在該CPU的緩存中且是未被修改過的,與主存中的數據一致,此種狀態可以在任何時刻,在有其他CPU讀取該內存時變成共享狀態。同樣地,當有CPU修改該緩存行內容時,該狀態可以變成被修改狀態。

Share(共享)

該緩存行可能被多個CPU進行緩存,且各緩存中的數據與主存中的數據是一致的,但某個CPU修改該緩存行時,其他CPU存儲的該緩存行就會被作廢,變成無效狀態。

Invalid(無效)

該緩存行可能被其他CPU修改。

對CPU緩存的四種操作

Local read/write 讀緩存裏的數據/將數據寫到緩存裏

Remote read/write 讀主存裏的數據/將數據寫到主存裏

四種狀態間的相互轉換關係

在典型的多核系統中,每一個核心都會有自己的緩存來共享主存匯流排,每一個CPU都會發出讀寫請求,而緩存的目的就是為了減少CPU讀寫共享主存的次數。

一個緩存,除了I狀態外,都可以滿足CPU的讀請求(Local read和Remote read)。

一個寫請求只有在該緩存行是M或者E狀態時才能被執行,如果當前緩存行處於S狀態,則必須先將該緩存行變成無效的狀態,這個操作通常通過廣播的方式來完成,此時既不允許不同的CPU同時修改同一個緩存行,即使修改該緩存行不同位置的數據也不允許。

處於M狀態的緩存行必須時刻監聽所有試圖讀該緩存行相對主存的操作,這種操作必須在CPU將該緩存寫回到主存並將狀態變為S狀態之前被延遲執行。

一個處於S狀態的緩存行必須監聽其他緩存使該緩存行無效或者獨享該緩存行的請求,並將緩存行變成無效。

處於E狀態的緩存行要監聽其他緩存讀該緩存中緩存行的操作,一旦有操作,需要將其變為S狀態,因此對於M和E,數據總是精確的,它們和緩存行的真正狀態使一致的,而S狀態可能是非一致的。如果一個緩存將處於S狀態的緩存行作廢了,另一個緩存可能已經獨享了該緩存行,但該緩存卻不會將該緩存行升遷為E狀態,這是因為其他緩存不會廣播它們作廢掉該緩存行的通知,同樣,由於緩存並沒有保存該緩存行複製的數量,也沒有辦法確定自身是否已經獨享了該緩存行。從這點來看,E狀態更像一種投機性優化,因為如果CPU想修改一個處於S狀態的緩存行,匯流排需要將所有該緩存行複製的值變成I狀態纔行,而修改E狀態卻不需要匯流排事務。

CPU多級緩存-亂序執行優化

處理器為提高運算速度而做出違背代碼原有順序的優化

亂序執行優化出現問題的原因

在單核時代處理器做出的優化可以保證執行結果不會遠離預期目標,但是,在多核時代卻並非如此。在多核時代,同時會有多個核同時執行指令,每一個核的指令都可能被亂序。另外,處理器還引入了L1,L2,...,Ln等多級緩存機制,每個核心都有自己的緩存機制,這樣就導致了邏輯次序上後寫入內存的數據未必真的最後寫入。最後就帶來一個問題,如果不做任何防護措施,處理器最終得出的結果和邏輯得出結果會大不相同。比如,在一個核上執行寫入操作,並在最後寫一個標記用來表示操作完畢,之後從另外一個核上通過判斷這個標記來判定所需要的數據是否已經就緒,這種做法就存在一定風險:標記位先被寫入但之前的操作卻並未完成(可能是未計算完成,也可能是數據沒有從處理器緩存刷新到主存中,最終導致另外的核使用了錯誤的數據)。

推薦閱讀:

相關文章