概述
問題的提出
避免CPU“空等”的現象
CPU和主存的速度差異
容量非常小,但是速度非常高,他就能提高CPU的訪存速率了。
為了充分發揮cache的作用,切實提高CPU的訪存速率,所以CPU的訪問數據和指令要求能大多數都能在cache中能夠取到,這樣就不需要到主存中去取了。這需要依靠局部性原理。
局部性原理
時間局部性:在最近的未來要用到的信息,很可能是現在正在使用的信息。
空間局部性:在最近的未來要用到的信息(指令和數據),很可能與現在正在使用的信息在存儲空間上是臨近的。
順序存放。
所以我們未來要用的信息很可能和我們現在使用的信息的存儲空間上是臨近的
交換的單位是以塊為單位的。
主存分成大小相同的塊,Cache也分成了大小相同的塊
主存和緩存按塊存儲,塊的大小相同,B為塊長。
M要遠遠大於C
塊內地址的位數決定了塊的大小。假如有16個字節,塊內地址就有4位???
主存和緩存的塊內地址是完全相同
標記是用來說明主存塊和cache的對應關系。
命中與未命中
緩存中有C塊
主存中有M塊M>>C
命中:主存塊已經調入緩存,主存塊與緩存塊建立了對應關系,用標記記錄與某緩存塊建立了對應關系的主存塊號。
未命中:主存塊未調入緩存,主存塊與緩存塊未建立對應關系。
Cache的命中率
CPU欲訪問的信息在Cache中的比率
設一個程序在執行期間,Cache的總命中次數為Nc,訪問主存的總次數為Nm,則命中率
命中率和Cache的容量和塊長有關
一般每塊可取4~8個字
塊長取一個存取周期內從主存調出的信息長度
失效率=1-H
Cache-主存系統的效率
效率e與 命中率 有關
如何計算平均訪問時間?命中時訪問Cache的時間加上不命中在主存的時間
設Cache命中率為h,訪問Cache的時間為tc,訪問主存的時間為tm
最小值是命中率為0的時候,最大值是命中率為1的時候
例題
設Cache的存儲周期是t,則主存的存儲周期是5t
Cache和主存同時訪問,不命中時訪問時間為5t
故系統的平均訪問時間為Ta=0.95 * t+0.05 * 5t=1.2t
設每個周期可存取的數據量為S,
則存儲系統帶寬為S/1.2t
不采用Cache時帶寬為S/5t
故性能為原來的
提高了3.17倍
若改為先訪問Cache再訪問主存的方式:
不命中時,訪問Cache耗時t
發現不命中后在訪問主存,耗時5t
總耗時6t
故系統的平均訪問時間為Ta=0.95 * t+0.05 * 6t = 1.25t
故性能為原來的5t/1.25t=4倍,提高了3倍
工作原理
當Cache要讀的時候
地址映射方式(本節最重要)
1.主存中的塊放到Cache中哪個位置?
(1)空位隨意放:全相聯映射
(2)對號入座:直接映射
(3)按號分組,組內隨意放:組相聯映射
2.對於(1),Cache滿了如何處理?對於(2)(3),對應位置被占用如何處理?
隨機(RAND)算法
先進先出(FIFO)算法
近期最少使用(LRU)算法
最不經常使用(LFU)算法
3.修改Cache中的內容后,如何保持主存中相應內容的一致性?
命中:全寫法(write-through)、寫回法(write-back)
不命中:寫分配法(write-allocate)、非寫分配法(not-write-allocate)
直接映射
主存當中的數據塊只能夠裝入到Cache的唯一位置。
把主存划分為若干個區,每個區大小和Cache是相等的,每個去的子塊數也是相等的。
每個區的對應單元只能對應Cache對應的單元。
主存地址的高m位就被划分為兩個部分——主存子塊標記,Cache子塊地址
記錄建立對應關系的緩存位的標記位當中
當緩存接到CPU接來的一個主存地址之后,根據中間的c位(Cache子塊地址)找到cache字塊,然后根據這個子塊的標記,判斷****是否與主存的高t位相符,如果相符,並且有效位**是有效(1)的,那么就表示Cache塊已經和主存的某一塊地址建立了對應關系。
如果不符合的話,就要從主存中讀入新的子塊。
每個緩存塊i 可以和若干個主存塊對應
每個主存塊j 只能和一個緩存塊對應
直接映射主存地址被划分為三個部分
j是Cache的塊號。i是主存的塊號
特點簡單,但是不夠靈活,容易發生沖突。
即使Cache有很多空位置,但是我還是要找到對應位置的來換
全相聯映射
大大提高了利用率,只要有位置就放。但是速度很慢。對比子塊標記很麻煩,每塊都要比較。
主存中的任一塊可以映射到緩存中的任一塊
組相聯映射
折中。
先把主存儲器划分為塊,在把每個塊划分為組。
先把Cache地址分成大小相同的組,每一個主存的數據塊可以裝入到一個組內的任何位置。
組間采用直接映射,組內全相聯映射。
01,23,45,67,。。。
二路組相聯映射。
速度快:直接映射
一般:組相聯
例子
全相聯
直接映射
組相聯
替換策略
- 隨機算法(RAND):隨機地確定替換的Cache塊。實現比較簡單,但沒有依據程序訪問的局部性原理,故可能命中率較低。(基本不考)
- 先進先出算法(FIFO): 選擇最早調入的行進行替換。容易實現,但也沒有依據程序訪問的局部性原理,可能會把一些經常使用的程序塊(如循環程序)也作為最早進入的Cache的塊替換掉。
- 近期最少使用算法(LRU):依據程序訪問的局部性原理選擇近期內長久未訪問過的存儲行作為替換的行,平均命中率要比FIFO高,是堆棧類算法。LRU算法對每行設置一個計數器,Cache每命中一次,命中行計數器清零,而其他各行計數器均加1,需要替換時比較各特定行的計數值,將計數值最大的行換出。
- 最不經常使用算法(LFU):將一段時間內被訪問次數最少的存儲行換出。每行也設置一個計數器,新行建立后從0開始計數,每訪問一次,被訪問的行計數器加1,需要替換時比較各特定行的計數值,將計數值最小的行換出。
例題
FIFO:把4替換掉
LRU:最近最少使用的是12,替換掉。從后往前數,最后那個就是最不常用的
LFU:4號塊用了3次,6號塊用了2次,其他均用了1次,需要更多的判斷依據。換12
只命中了1次。
在組內是用不同的替換算法的。
FIFO:在第0組中,最先調入的是4號塊,標記為1,命中0次
列表的方法。
每次都放到每組的最下面,然后出去的就是先進先出的。
如果用了就把它移上去。
LFU:操作系統。
寫策略
命中
如果對Cache的內容進行修改,就要修改主存中對應的塊。
命中:要訪問的主存內容已經在Cache當中。
這塊要被換掉之后才把主存的修改掉。寫回法。加多一個臟位
寫回法(write-back):當CPU對Cache寫命中時,只修改Cache的內容,而不立即寫入主存,只有當此塊被換出時才寫回主存。
每次有修改就改,不用臟位了,但是增加訪存次數。
全寫法(write-through):當CPU對Cache寫命中時,必須把數據同時寫入Cache和主存,一般使用寫緩沖(write buffer)
寫的太頻繁,會有隊列的溢出。
未命中
寫分配法(write-allocate):把主存中的塊調入Cache,在Cache中修改,搭配寫回法使用。
缺點:每次不命中都要從主存中讀取塊。
非寫分配法(not-write-allocate):只寫入主存,不調入Cache,搭配全寫法使用。