CPU Cache是CPU高速緩沖存儲(chǔ)器的簡(jiǎn)稱,本文將其簡(jiǎn)稱為"緩存"或者"Cache".
本篇首先從計(jì)算機(jī)的存儲(chǔ)層次出發(fā)介紹計(jì)算機(jī)的性能瓶頸,然后以Intel處理器為例介紹緩存的發(fā)展,隨后介紹緩存提升CPU性能的局部性原理,最后分析緩存大小對(duì)CPU性能的影響。
一、計(jì)算機(jī)性能的瓶頸
在馮諾依曼架構(gòu)下,計(jì)算機(jī)存儲(chǔ)器是分層次的,存儲(chǔ)器的層次結(jié)構(gòu)如下圖所示,是金字塔形狀。從上到下依次是寄存器、L1緩存、L2緩存,L3緩存主存(內(nèi)存)、硬盤等等。
離CPU越近的存儲(chǔ)器,訪問速度越來越快,容量越來越小,每字節(jié)的成本也越來越昂貴。
如一個(gè)主頻為3.0GHZ的CPU,寄存器的速度最快,可以在1個(gè)時(shí)鐘周期內(nèi)訪問,一個(gè)時(shí)鐘周期(CPU中基本時(shí)間單位)大約是0.3納秒,內(nèi)存訪問大約需要120納秒,固態(tài)硬盤訪問大約需要50-150微秒,機(jī)械硬盤訪問大約需要1-10毫秒。
電子計(jì)算機(jī)剛出來的時(shí)候,其實(shí)CPU是沒有緩存Cache的,那個(gè)時(shí)候的CPU主頻很低,甚至沒有內(nèi)存高,CPU都是直接讀寫內(nèi)存的。隨著時(shí)代的發(fā)展,技術(shù)的革新,從1980年代開始,差距開始迅速擴(kuò)大,CPU的速度遠(yuǎn)遠(yuǎn)超過內(nèi)存的速度,在馮諾依曼架構(gòu)下,CPU訪問內(nèi)存的速度也就成了計(jì)算機(jī)性能的瓶頸!
圖片來源于:How L1 and L2 CPU Caches Work, and Why They're an Essential Part of Modern Chips
為了彌補(bǔ)CPU與內(nèi)存兩者之間的性能差異,也就是要加快CPU訪問內(nèi)存的速度,就引入了緩存CPU Cache,緩存的速度僅次于寄存器,充當(dāng)了CPU與內(nèi)存之間的中間角色。
二、緩存及其發(fā)展歷史
緩存CPU?Cache用的是 SRAM(Static Random-Access Memory)存儲(chǔ),也叫靜態(tài)隨機(jī)存儲(chǔ)器。其只要有電,數(shù)據(jù)就可以保持存在,而一旦斷電,數(shù)據(jù)就會(huì)丟失。
CPU Cache 通常分為大小不等的3級(jí)緩存,分別是 L1 Cache、L2 Cache 和 L3 Cache。常見的Cache典型分布圖如下:
這里以intel系列為例,回顧C(jī)ache發(fā)展歷史。
在80286之前,那個(gè)時(shí)候是沒有緩存Cache的,那個(gè)時(shí)候的CPU主頻很低,甚至沒有內(nèi)存高,CPU都是直接讀寫內(nèi)存的。
從80386開始,這個(gè)CPU速度和內(nèi)存速度不匹配問題已經(jīng)開始展露,并且差距開始迅速擴(kuò)大,慢速度的內(nèi)存成為了計(jì)算機(jī)的瓶頸,無法充分發(fā)揮CPU的性能,為解決這個(gè)問題,Intel主板支持外部Cache,來配合80386運(yùn)行。
80486將L1 Cache(大小8KB)放到CPU內(nèi)部,同時(shí)支持外接Cache,即L2 Cache(大小從128KB到256KB),但是不分指令和數(shù)據(jù)。雖然L1 Cache大小只有8KB,但其實(shí)對(duì)那時(shí)候CPU來說夠用了,我們來看一副緩存命中率與L1、L2大小的關(guān)系圖:
圖片來源于:How L1 and L2 CPU Caches Work, and Why They're an Essential Part of Modern Chips。
從上圖我們可以發(fā)現(xiàn),增大L1 cache對(duì)于CPU來說好處不太明顯,緩存命中率并沒有顯著提升,成本還會(huì)更昂高,所以性價(jià)比不高。而隨著L2 cache 大小的增加,緩存總命中率會(huì)急劇上升,因此容量更大、速度較慢、更便宜的L2成為了更好的選擇。
等到Pentium-1/80586,也就是我們熟悉的奔騰系列,由于Pentium采用了雙路執(zhí)行的超標(biāo)量結(jié)構(gòu),有2條并行整數(shù)流水線,需要對(duì)數(shù)據(jù)和指令進(jìn)行雙重的訪問,為了使得這些訪問互不干涉,于是L1 Cache被一分為二,分為指令Cache和數(shù)據(jù)Cache(大小都是8K)【將數(shù)據(jù)和指令分別存取的存取結(jié)構(gòu)叫做哈佛結(jié)構(gòu),區(qū)別于混在一起的馮·諾伊曼結(jié)構(gòu)】,此時(shí)的L2 Cache還是在主板上,再后來Intel推出了[Pentium Pro]/80686,為了進(jìn)一步提高性能,L2 Cache被正式放到CPU內(nèi)部。
在CPU外面,DRAM內(nèi)存還是那么一套內(nèi)存,硬盤也是那么一套不區(qū)分指令和數(shù)據(jù)的硬盤。因而可以說x86 CPU是在內(nèi)部采用哈佛結(jié)構(gòu)、外部仍然是馮·諾伊曼結(jié)構(gòu)。實(shí)際上除了少數(shù)單片機(jī)、DSP等設(shè)備,誰(shuí)也不會(huì)最外層的存儲(chǔ)設(shè)備都區(qū)分?jǐn)?shù)據(jù)和指令。所以這種內(nèi)部哈佛,外部馮·諾伊曼結(jié)構(gòu)的做法似乎已經(jīng)成了業(yè)界共識(shí)。
后來CPU多核時(shí)代來臨,Intel的Pentium D、Pentium E系列,CPU內(nèi)部每個(gè)核心都有自己的L1、L2 Cache,但他們并不共享,只能依靠總線來傳遞同步緩存數(shù)據(jù)。最后Core Duo酷睿系列的出現(xiàn),L2 Cache變成多核共享模式,采用Intel的“Smart cache”共享緩存技術(shù),到此為止,就確定了現(xiàn)代緩存的基本模式。
如今CPU Cache通常分為大小不等的3級(jí)緩存,分別是 L1 Cache、L2 Cache 和 L3 Cache,L3 高速緩存為多個(gè) CPU 核心共用的,而L2則被每個(gè)核心單獨(dú)占據(jù),另外現(xiàn)在有的CPU已經(jīng)有了L4 Cache,未來可能會(huì)更多。
三、緩存如何彌補(bǔ)CPU與內(nèi)存的性能差異?
緩存主要是利用局部性原理來提升計(jì)算機(jī)的整體性能。因?yàn)榫彺娴男阅軆H次于寄存器,而CPU與內(nèi)存兩者之間的產(chǎn)生的分歧,主要是二者存取速度數(shù)量級(jí)的差距,盡可能多地讓CPU去存取緩存,同時(shí)減少CPU直接訪問主存的次數(shù),這樣計(jì)算機(jī)的性能就自然而然地得到巨大的提升。
所謂局部性原理,主要分為空間局部性與時(shí)間局部性:
時(shí)間局部性:被引用過一次的存儲(chǔ)器位置在未來會(huì)被多次引用(通常在循環(huán)中)。
空間局部性:如果一個(gè)存儲(chǔ)器的位置被引用,那么將來它附近的位置也會(huì)被引用。
緩存會(huì)把CPU最近訪問主存(內(nèi)存)中的指令和數(shù)據(jù)臨時(shí)儲(chǔ)存,因?yàn)楦鶕?jù)局部性原理,這些指令和數(shù)據(jù)在較短的時(shí)間間隔內(nèi)很可能會(huì)被以后多次使用到,其次是當(dāng)從主存中取回這些數(shù)據(jù)時(shí),會(huì)同時(shí)取回與其位置相鄰的主存單元的存放的數(shù)據(jù)臨時(shí)儲(chǔ)存到緩存中,因?yàn)樵撝噶詈蛿?shù)據(jù)附近的內(nèi)存區(qū)域,在較短的時(shí)間間隔內(nèi)也可能會(huì)被多次訪問。
當(dāng)CPU去訪問指令和數(shù)據(jù)時(shí),首先去訪問L1 Cache,如果命中,則會(huì)直接從對(duì)應(yīng)的緩存中取數(shù)據(jù),而不必每次去訪問主存,如果沒命中,會(huì)再去L2 Cache中找,依次類推,如果L3 Cache中不存在,就去內(nèi)存中找。
四、L1緩存是不是越大越好?
L1增大,會(huì)提高L1的命中率,但L1緩存是不是越大越好?
4.1?增大L1對(duì)訪問延遲的影響
一個(gè)實(shí)際的例子: 從Intel Sunny Cove (Core第10代) 開始L1 cache從32K (指令) +32K(數(shù)據(jù)) 的組合變成了32K (指令) +48K (數(shù)據(jù)) 的組合。這樣的后果就是L1 cache的訪問性能下降,從4個(gè)cycle變成5個(gè)cycle。增大L1會(huì)提高命中率,同時(shí)延遲也增加了。那么這一升一降對(duì)平均訪問時(shí)間(AMAT)有什么影響呢?
下面用一個(gè)簡(jiǎn)單的例子來說明一下L1訪問時(shí)間對(duì)AMAT的影響。假設(shè)我們有三層的memory hierarchy (L1, L2, offchip RAM) ,其中L2訪問時(shí)間為10 cycle,off-chip RAM訪問時(shí)間為200 cycle。假設(shè)32KB L1-D的情況下L1,L2的hit rate大致為90%,9%,增加至48KB L1-D的Sunny Cove L1,L2 hit rate提升為95%,4%,那么對(duì)應(yīng)的
Sunny Cove平均訪問時(shí)間約為?
0.95*5+0.04*10+0.01*200=7.15 cycle.
Sunny Cove之前的microarchitecture的平均訪問時(shí)間約為
0.90*4+0.09*10+0.01*200=6.5 cycle.
簡(jiǎn)單的模型估算可以看出,即便增大L1 size可以提升L1 hit rate,然而L1訪問延時(shí)的增加,還是會(huì)使得平均內(nèi)存訪問延時(shí)增加了~10%。這也是為什么L1 cache size長(zhǎng)時(shí)間來沒有太大改動(dòng)的原因。
綜上,L1大小將直接影響訪問時(shí)間,而訪問L1的時(shí)間又會(huì)直接影響到平均內(nèi)存訪問時(shí)間(average memory access time - AMAT),對(duì)整個(gè)CPU的性能產(chǎn)生巨大影響。
4.2 限制L1訪問延時(shí)的原因是什么?
在系統(tǒng)啟動(dòng)過程中,僅在很早期啟動(dòng)階段CPU處于實(shí)模式,開啟paging之后,CPU接收的load/store指令對(duì)應(yīng)的地址均為虛擬地址,在訪問L1 cache的時(shí)候還需要經(jīng)過虛擬地址VA到物理地址PA的轉(zhuǎn)換?,F(xiàn)代CPU通常采用virtual index physical tag的L1結(jié)構(gòu)?。這種L1結(jié)構(gòu)的一大好處就是可以在index cache set的時(shí)候同時(shí)訪問TLB (相當(dāng)于隱藏了部分L1訪問延時(shí)),一個(gè)x64下的L1訪問示意圖如下所示。
TLB:Translation lookaside buffer,即旁路轉(zhuǎn)換緩沖,或稱為頁(yè)表緩沖
對(duì)于4KB大小的page,共有12bit page offset,其中低6bit為cacheline offset (64B cachelinesize),剩余6bit作為L(zhǎng)1 index bits,這也就意味著L1只能限制于64個(gè)cache set。對(duì)于32KB L1-D,也就意味著其每個(gè)set對(duì)應(yīng)8 way (32KB/64/64 = 8) 。Sunny Cove的48KB L1-D對(duì)應(yīng)每個(gè)set12 way。由上圖可以看出,L1訪問延時(shí)的關(guān)鍵路徑為TLB訪問以及TLB hit之后對(duì)相應(yīng)L1 cache set的TAG matching,由于cache set是簡(jiǎn)單的lookup,我們可以認(rèn)為在TLB查詢結(jié)束得到PPN的時(shí)候立即可以進(jìn)行TAG matching。(TLB也是一個(gè)小的set-associatative cache,也需要進(jìn)行TAG matching。因此訪問時(shí)間要長(zhǎng)于L1 set lookup)。因此,TLB的查詢時(shí)間和L1的associativity (即圖中的TAG matching)決定了L1的訪問延時(shí)。
為了保證L1訪問延時(shí)可以做的足夠低,通常需要設(shè)計(jì)L1的associativity盡量小。因此在Sunny Cove之前通常為8 way。這里Sunny Cove增加了一個(gè)cycle的L1訪問延時(shí),不確定是由TLB的改動(dòng)引起的還是L1 associativity由8 way增加到12 way。但是總的來說,我們可以看出L1為什么不能設(shè)計(jì)得很大,主要是由于virtual index physical tag的結(jié)構(gòu)引起的。
另一方面,L1 cache 32kb 是算好能覆蓋整個(gè)4KB頁(yè)的,從第一代core到現(xiàn)在十代都是這么設(shè)計(jì)的。每個(gè)set有8個(gè)way,也就是說可以同時(shí)緩存8頁(yè),加大容量一方面提高延遲的同時(shí)可能會(huì)導(dǎo)致很大一部分way在很多時(shí)候是閑置浪費(fèi)性能。
總的來說,增加cache line的大小,但是相應(yīng)的cache miss的延遲會(huì)大大增加,尤其是考慮到L1會(huì)緩存虛擬地址,一旦miss意味著penalty會(huì)增加更多。另外如果增加wayness或者sets,會(huì)造成尋址延遲增高,也是得不償失。
另外,L1 cache的替換以及prefetch策略都是很復(fù)雜的,這些也會(huì)導(dǎo)致延遲的提高對(duì)性能的影響會(huì)大于容量的提高。
4.3 蘋果M1的L1為什么會(huì)比X-86的L1大?
為什么蘋果的M1可以做到192KB的L1-I(128KB L1-D),同時(shí)保證3 cycle的訪問延時(shí)呢?
首先一點(diǎn)蘋果的最高主頻相對(duì)Intel/AMD的desktop/server line的CPU要低一些,因此在時(shí)序上約束相對(duì)放松一些(主要是tag matching的comparator路徑的關(guān)鍵路徑)。其次一點(diǎn),也是最關(guān)鍵的M1對(duì)應(yīng)的MacOS采用的是16KB page而非x86的4KB page。
由上圖可知如果擴(kuò)大page size(16KB對(duì)應(yīng)14bit),相當(dāng)于增加了2bit的index bits,這樣的話L1 cache set數(shù)目可以增加4倍(在保持associativity的前提下),因此M1的L1-I正好是Sunny Cove的4倍(192KB/48KB = 4)。M1的L1-D大小是128KB(4倍于32KB)。
對(duì)于問題中的L1 cache來講,其實(shí)更多的是系統(tǒng)層面的取舍(page size增加也會(huì)導(dǎo)致內(nèi)存浪費(fèi),內(nèi)存碎片等問題,但是同時(shí)也會(huì)減輕頁(yè)表的壓力,增加TLB coverage)。不過也僅限于蘋果,其M1的產(chǎn)品只是MacBook一個(gè)設(shè)備,可以做更多的定制,對(duì)于x86來講,歷史包袱和眾多設(shè)備兼容性的問題,使其很難做到像蘋果這種更加靈活的架構(gòu)設(shè)計(jì)。
審核編輯:黃飛
?
評(píng)論
查看更多