CPU在一段較短的時間內,是對連續地址的一段很小的主存空間頻繁地進行訪問,而對此范圍以外地址的訪問甚少,這種現象稱為程序訪問的局部性。
Cache技術就是利用程序訪問的局部性原理,把程序中正在使用的部分(活躍塊)存放在一個小容量的高速Cache中,使CPU的訪存操作大多針對Cache進行,從而解決高速CPU和低速主存之間速度不匹配的問題,使程序的執行速度大大提高。
Cache技術是為了解決CPU和主存之間速度不匹配而采用的一項重要技術。
CPU與Cache之間的數據交換是以字為單位的,而Cache與主存之間的數據交換則是以塊為單位的。一個塊由若干個定長字組成。
當CPU讀取主存中的一個字時,該字的主存地址被發給Cache和主存,此時,Cache控制邏輯依據地址判斷該字當前是否存在于Cache中:若在,該字立即被從Cache傳送給CPU;若不在,則用主存讀周期把該字從主存讀出送到CPU,同時把含有這個字的整個數據塊從主存讀出送到Cache中,并采用一定的替換策略將Cache中的某一塊替換掉,替換算法由Cache管理邏輯電路來實現。
Cache的命中率
Cache的工作效率通常用“命中率”來表示。
命中率指的是CPU要訪問的信息在Cache中的概率,Cache的命中率越高,CPU訪問主存的速度就越接近訪問Cache的速度。通常Cache的容量越大,存儲的塊也越多,CPU的命中率就越高。但是,當Cache的容量達到一定值時,命中率并不會隨著容量的增大而增加,而且Cache容量的增大將導致成本的增加,所以,Cache的容量一般是命中率與成本價格的折中。
命中率h與程序的行為、Cache的容量、組織方式、塊的大小有關。
Cache的替換算法
Cache的容量很小,它保存的內容只是主存內容的一個子集,且Cache與主存的數據交換是以塊為單位的。為了把信息放到Cache中,必須應用某種函數把主存地址定位到Cache中,這稱為地址映射。
Cache的地址映射方式有直接映射、全相聯映射和組相聯映射。
假設某臺計算機主存容量為l MB,被分為2048塊,每塊512B;
Cache容量為8KB,被分為16塊,每塊也是512B。
下面以此為例介紹三種基本的地址映射方法。
1. 直接映射
直接映射的Cache組織如圖所示。
主存中的一個塊只能映射到Cache的某一特定塊中去。例如,主存的第0塊、第16塊、……、第2032塊,只能映射到Cache的第0塊;而主存的第1塊、第17塊、……、第2033塊,只能映射到Cache的第1塊……。

直接映射是最簡單的地址映射方式,它的硬件簡單,成本低,地址變換速度快,而且不涉及替換算法問題。但是這種方式不夠靈活,Cache的存儲空間得不到充分利用,每個主存塊只有一個固定位置可存放,容易產生沖突,使Cache效率下降,因此只適合大容量Cache采用。
例如,如果一個程序需要重復引用主存中第0塊與第16塊,最好將主存第0塊與第16塊同時復制到Cache中,但由于它們都只能復制到Cache的第0塊中去,即使Cache中別的存儲空間空著也不能占用,因此這兩個塊會不斷地交替裝入Cache中,導致命中率降低。
2. 全相聯映射
圖3-15 是全相聯映射的Cache組織,主存中任何一塊都可以映射到Cache中的任何一塊位置上。

全相聯映射方式比較靈活,主存的各塊可以映射到Cache的任一塊中,Cache的利用率高,塊沖突概率低,只要淘汰Cache中的某一塊,即可調入主存的任一塊。但是,由于Cache比較電路的設計和實現比較困難,這種方式只適合于小容量Cache采用。
3. 組相聯映射
組相聯映射實際上是直接映射和全相聯映射的折中方案,其組織結構如圖3-16所示。
主存和Cache都分組,主存中一個組內的塊數與Cache中的分組數相同,組間采用直接映射,組內采用全相聯映射。
也就是說,將Cache分成u組,每組v塊,主存塊存放到哪個組是固定的,至于存到該組哪一塊則是靈活的。例如,主存分為256組,每組8塊,Cache分為8組,每組2塊。

主存中的各塊與Cache的組號之間有固定的映射關系,但可自由映射到對應Cache組中的任何一塊。例如,主存中的第0塊、第8塊……均映射于Cache的第0組,但可映射到Cache第0組中的第0塊或第1塊;主存的第1塊、第9塊……均映射于Cache的第1組,但可映射到Cache第1組中的第2塊或第3塊。
常采用的組相聯結構Cache,每組內有2、4、8、16塊,稱為2路、4路、8路、16路組相聯Cache。組相聯結構Cache是前兩種方法的折中方案,適度兼顧二者的優點,盡量避免二者的缺點,因而得到普遍采用。
替換策略
Cache工作原理要求它盡量保存最新數據,當從主存向Cache傳送一個新塊,而Cache中可用位置已被占滿時,就會產生Cache替換的問題。
替換問題與Cache的組織方式緊密相關:對直接映射Cache來說,只要把此可用位置上的主存塊換出Cache即可;對全相聯和組相聯Cache來說,要從若干個可用位置中選取一個位置,把其中的主存塊換出Cache。
常用的替換算法有下面三種。
1. 最不經常使用(LFU)算法
LFU(Least Frequently Used,最不經常使用)算法將一段時間內被訪問次數最少的那個塊替換出去。每塊設置一個計數器,從0開始計數,每訪問一次,被訪塊的計數器就增1。當需要替換時,將計數值最小的塊換出,同時將所有塊的計數器都清零。
這種算法將計數周期限定在對這些特定塊兩次替換之間的間隔時間內,不能嚴格反映近期訪問情況,新調入的塊很容易被替換出去。
2. 近期最少使用(LRU)算法
LRU(Least Recently Used,近期最少使用)算法是把CPU近期最少使用的塊替換出去。這種替換方法需要隨時記錄Cache中各塊的使用情況,以便確定哪個塊是近期最少使用的塊。每塊也設置一個計數器,Cache每命中一次,命中塊計數器清零,其他各塊計數器增1。當需要替換時,將計數值最大的塊換出。
LRU算法相對合理,但實現起來比較復雜,系統開銷較大。這種算法保護了剛調入Cache的新數據塊,具有較高的命中率。
3. 隨機替換
最簡單的替換算法是隨機替換。隨機替換算法完全不管Cache的情況,簡單地根據一個隨機數選擇一塊替換出去。隨機替換算法在硬件上容易實現,且速度也比前兩種算法快。缺點則是降低了命中率和Cache工作效率。
Cache命中率除了和替換算法有關外,還與Cache的容量及塊的大小有
關。
寫回算法
由于Cache的內容只是主存內容的一個子集,應當與主存內容保持一致,而CPU對Cache的寫入更改了Cache的內容。為此,可選用寫操作策略使Cache內容與主存內容保持一致。
寫回法
當CPU寫Cache命中時,只修改Cache的內容,而不是立即寫入主存;只有當此塊被換出時才寫回主存。
使用這種方法寫Cache和寫主存異步進行,顯著減少了訪問主存的次數,但是存在數據不一致的隱患。實現這種方法時,每個Cache塊必須配置一個修改位,以反映此塊是否被CPU修改過。
全寫法
當寫 Cache命中時,Cache與主存同時發生寫修改。
使用這種方法寫Cache和寫主存同步進行,因而較好地維護了Cache與主存的內容一致性。實現這種方法時,Cache中的每個塊無需設置修改位以及相應的判斷邏輯,但由于Cache對CPU向主存的寫操作沒有高速緩沖功能,從而降低了Cache的功效。
寫一次法
寫一次法是基于寫回法并結合全寫法的寫操作策略,寫命中與寫未命中的處理方法與寫回法基本相同,只是第一次寫命中時要同時寫入主存,以便于維護系統全部Cache的一致性。