memory cache 直接映射、全相聯映射和組相聯映射

cpu的執行速度很快,cpu從memory讀取數據速度很慢,導致cpu需要等memory,爲了提高cpu的效率,根據程序的局部性原理(現在訪問的數據很有可能以後還會訪問),引入了讀寫比較快的memory cache,cache用來存放剛剛訪問的memory的數據,這樣下次再需要從memory讀寫數據時,可以直接從cache裏面讀,速度快了很多,提高了cpu的效率。

cache比memory速度快,但是也比memory價錢貴,所以cache一般比較小,比如memory可能有4G、但cache只有64k。既然cache不能存放所有的memory數據,那memory中的數據應該存放在cache的什麼位置呢?希望達成的效果是最近經常訪問的數據都在cache裏面,並且查找也要快速。

考慮下面一個程序,假設這個程序在memory中的存放如下圖1,這個時候在運行程序的時候肯定是希望code和data都被cache。爲了達到這個目標,有3種方案可以選擇,圖2直接映射,圖3全相聯映射,圖4組相聯映射。

int a = 0;

int main()
{
    while(a < 100) {a++;}
}

 

                                                   圖1 程序的內存分佈

                                                   圖2 直接映射

假設cache有4個cache line,memory比較多,另外各圖的方框表示的空間大小相同,即一個memory的方框和一個cache的方框(cache line)大小相同。

直接映射,就是把memory按照cache line的數量分組,有4個cache line,那麼memory每4個一組,每一組直接對應cache的相應line。memory第一組的0-3分別映射到cache的line 0-3。第二組的4-7分別映射到cache的line 0-3。

通過直接映射,code被放到了cache line 0和1,data也被映射到了cache line 0。這個時候的問題是,執行代碼的時候命中cache,讀寫數據的時候不命中,然後更新cache,把cache的內容換爲data。再執行的代碼的時候發現code被從cache中移除了,導致cache不命中,然後又更新cache,換成code。讀寫數據的時候就又會cache不命中,更新cache;然後又代碼cache不命中....嗯,需要嘗試一下其他的映射方式了

                                                   圖3 全相聯映射

全相聯映射,不規定memory在cache中的位置了,隨意放。比如memory 0可以放在任意的cache line。其他memory也是,所有的cache line都可以放。

通過全相聯映射,可能的結果是1)code放在了cache line 0 & 1,data放在了cache line 2,也可能2)code 0放在cache line 3,code 1放在cache line 2,data放在cache line 0。至少都在cache裏面了。存在的問題是,當cpu拿着內存地址來找是否在cache中時,就會比較費力了。只拿着一個內存地址來找cache的話,只能把cache遍歷一遍了,不太好。嗯,再考慮另外一種映射方案吧

                                                   圖4 組相聯映射(每組2個爲例)

組相聯映射,希望可以把程序都放在cache,同時希望查找要方便。回想直接映射的時候,因爲memory 0和memory 4都映射到了cache line 0,所以導致頻繁的cache不命中/更新。如果cache line 0可以同時把memory 0和memory 4都保存了,就會一直cache命中了……

但是一個cache line只能存放一個memory方框的內容(因爲一個cache line的大小等於一個memory方框的大小),怎麼辦呢?考慮把cache line 0和cache line 1當成一個大的cache line吧,也就是把兩個相鄰的cache line當作一組、組成一個大的cache line,然後採用直接映射。

這樣,之前的4個cache line變成了2個大的cache line,按照直接映射的規則,把memory按照cache line的數量分組,有2個大的cache line,那麼memory每2個一組,每一組直接對應cache的相應line。這樣memory第一組的0-1分別映射到大cache line 0-1(組0和組1),第二組的2-3分別映射到大cache line 0-1,第三組的4-5分別映射到大cache line 0-1。

映射到大的cache line之後需要決定具體放到哪個小的cache line,這個時候是隨意的,哪個都可以。比如memory 0映射到組0(大的cache line 0)後,放在cache line 1;memory 1映射到組1(大的cache line 1)後,放在cache line 2;memory 4映射到組0(大的cache line 0)後,放在cache line 0。

這種映射可以把相關的代碼數據都放在cache,同時查找也方便點,因爲一個組裏面的cache line數量比較少。這種方式也算是可以達成最初的期望:最近經常訪問的數據都在cache裏面,並且查找也要快速。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章