「底層原理」深入理解Cache
存儲器是分層次的,離CPU越近的存儲器,速度越快,每字節的成本越高,同時容量也因此越小。寄存器速度最快,離CPU最近,成本最高,所以個數容量有限,其次是高速緩存(緩存也是分級,有L1,L2等緩存),再次是主存(普通內存),再次是本地磁盤。

寄存器的速度最快,可以在一個時鐘周期內訪問,其次是高速緩存,可以在幾個時鐘周期內訪問,普通內存可以在幾十個或幾百個時鐘周期內訪問。

存儲器分級,利用的是局部性原理。我們可以以經典的閱讀書籍為例。我在讀的書,捧在手里(寄存器),我最近頻繁閱讀的書,放在書桌上(緩存),隨時取來讀。當然書桌上只能放有限幾本書。我更多的書在書架上(內存)。如果書架上沒有的書,就去圖書館(磁盤)。我要讀的書如果手里沒有,那么去書桌上找,如果書桌上沒有,去書架上找,如果書架上沒有去圖書館去找??梢詫拇嫫鳑]有,則從緩存中取,緩存中沒有,則從內存中取到緩存,如果內存中沒有,則先從磁盤讀入內存,再讀入緩存,再讀入寄存器。
本系列的文章重點介紹緩存cache。了解如何獲取cache的參數,了解緩存的組織結構,了解cache對程序的影響,了解如何利用cache提升性能。

本文作為系列文章的第一篇,講述的如何獲取cache的組成結構和如何獲取cache的參數。
cache分成多個組,每個組分成多個行,linesize是cache的基本單位,從主存向cache遷移數據都是按照linesize為單位替換的。比如linesize為32Byte,那么遷移必須一次遷移32Byte到cache。 這個linesize比較容易理解,想想我們前面書的例子,我們從書架往書桌搬書必須以書為單位,肯定不能把書撕了以頁為單位。書就是linesize。當然了現實生活中每本書頁數不同,但是同個cache的linesize總是相同的。
所謂8路組相連( 8-way set associative)的含義是指,每個組里面有8個行。
我們知道,cache的容量要遠遠小于主存,主存和cache肯定不是一一對應的,那么主存中的地址和cache的映射關系是怎樣的呢?
拿到一個地址,首先是映射到一個組里面去。如何映射?取內存地址的中間幾位來映射。
舉例來說,data cache: 32-KB, 8-way set associative, 64-byte line size表示Cache總大小為32KB,8路組相連(每組有8個line),每個line的大小linesize為64Byte,OK,我們可以很輕易的算出一共有32K/8/64=64 個組。
對于32位的內存地址,每個line有2^6 = 64Byte,所以地址的【0,5】區分line中的那個字節。一共有64個組。我們取內存地址中間6為來hash查找地址屬于那個組。即內存地址的【6,11】位來確定屬于64組的哪一個組。組確定了之后,【12,31】的內存地址與組中8個line挨個比對,如果【12,31】為與某個line一致,并且這個line為有效,那么緩存命中。
OK,cache分成三類:
直接映射高速緩存,這個簡單,即每個組只有一個line,選中組之后不需要和組中的每個line比對,因為只有一個line。
組相聯高速緩存,這個就是我們前面介紹的cache。 S個組,每個組E個line。
全相聯高速緩存,這個簡單,只有一個組,就是全相聯。不用hash來確定組,直接挨個比對高位地址,來確定是否命中??梢韵胍娺@種方式不適合大的緩存。想想看,如果4M 的大緩存
描述一個cache需要以下參數:
- cache分級,L1 cache, L2 cache, L3 cache,級別越低,離cpu越近
- cache的容量
- cache的linesize
- cache 每組的行個數.
組的個數完全可以根據上面的參數計算出來,所以沒有列出來.Intel手冊中用這樣的句子來描述cache:8-MB L3 Cache, 16-way set associative, 64-byte line size ,如何獲取cache的參數呢,到了我們的老朋友cpuid指令,當eax為0x2的時候,cpuid指令獲取到cache的參數. 下面給出代碼:


我的電腦上運行結果如上圖,查看intel的手冊可知
