Cache(高速緩存)的發(fā)展是計(jì)算歷史上最重要的事件之一。幾乎所有的現(xiàn)代CPU內(nèi)核,從ARM Cortex-A5這樣的超低功耗芯片到最高端的Intel Core i9都使用cache。即使是更高端的微控制器也經(jīng)常有小型cache,或作為選項(xiàng)提供,即使是在超低功耗設(shè)計(jì)中,其性能優(yōu)勢(shì)也實(shí)在是不容忽視。
緩存的發(fā)明是為了解決一個(gè)重要問(wèn)題。在計(jì)算機(jī)發(fā)展的早期幾十年里,主存非常慢,而且非常昂貴,但CPU也不是特別快。從20世紀(jì)80年代開始,這一差距開始迅速擴(kuò)大。微處理器的時(shí)鐘速度突飛猛進(jìn),但內(nèi)存訪問(wèn)時(shí)間卻沒有明顯改善。隨著這一差距的擴(kuò)大,越來(lái)越明顯的是,需要一種新型的快速存儲(chǔ)來(lái)彌補(bǔ)這一差距。
雖然只到2000年,但20世紀(jì)80年代開始差異越來(lái)越大,導(dǎo)致了第一批CPU cache開發(fā)出來(lái)。
Cache的工作原理
CPU cache是小型內(nèi)存池,用于存儲(chǔ)CPU下一步最可能需要的信息。哪些信息加載到cache取決于復(fù)雜的算法和對(duì)編程代碼的某些假設(shè)。Cache系統(tǒng)的目標(biāo)是確保CPU在尋找下一位數(shù)據(jù)時(shí),已經(jīng)將其加載到cache(也稱為‘cache hit’)。
另一方面,cache miss意味著CPU不得不去別處尋找數(shù)據(jù)。這就是L2 cache發(fā)揮作用的地方,雖然它比較慢,但卻更大。有些處理器使用inclusive cache設(shè)計(jì)(意味著存儲(chǔ)在L1 cache中的數(shù)據(jù)也會(huì)復(fù)制到L2 cache中),而其他處理器則是exclusive的(意味著這兩個(gè)cache從不共享數(shù)據(jù))。如果在L2 cache中找不到數(shù)據(jù),CPU就會(huì)繼續(xù)往下找L3(通常仍在芯片上),然后是L4(如果存在)和主內(nèi)存(DRAM)。
這張圖顯示了一個(gè)hit rate恒定的L1 cache與一個(gè)更大的L2 cache之間的關(guān)系。請(qǐng)注意,總hit rate隨著L2大小的增加而急劇上升。一個(gè)更大、更慢、更便宜的L2可以提供大型L1的所有優(yōu)勢(shì),但沒有芯片尺寸和功耗的影響。大多數(shù)現(xiàn)代L1 cache的hit rate都遠(yuǎn)遠(yuǎn)高于這里顯示的理論上的50%,Intel和AMD的cache hit rate通常都在95%或更高。
下一個(gè)重要的點(diǎn)是set-associativity。每個(gè)CPU都包含一種特定類型的RAM,稱為tag RAM。Tag RAM是所有可以映射到任何給定cache塊的內(nèi)存位置的記錄。如果一個(gè)cache是完全關(guān)聯(lián)的,這意味著任何RAM數(shù)據(jù)塊都可以存儲(chǔ)在任何一塊cache中。這種系統(tǒng)的優(yōu)點(diǎn)是hit rate高,但搜索時(shí)間非常長(zhǎng),CPU必須在搜索主存之前查看整個(gè)cache以確定數(shù)據(jù)是否存在。
當(dāng)然,還有直接映射的cache。直接映射的cache是指每個(gè)cache塊可以包含一個(gè)且只有一個(gè)主存塊。這種類型的cache可以被快速搜索,但是由于它是1:1映射到內(nèi)存位置,因此hit rate很低。介于這兩個(gè)極端之間的是n-way associative cache。2-way associative cache(Piledriver的L1是2-way)意味著每個(gè)主內(nèi)存塊可以映射到兩個(gè)cache塊中的一個(gè)。8-way意味著每個(gè)主內(nèi)存塊可以映射到8個(gè)cache塊中的一個(gè)。Ryzen的L1指令cache是4-way associative,而L1數(shù)據(jù)cache是8-way set associative。
接下來(lái)的兩圖片顯示了hit rate是如何隨著set-associativity而提高的。請(qǐng)記住,像hit rate這樣的東西是非常特殊的,不同的應(yīng)用會(huì)有不同的hit rate。
為什么CPU的cache越來(lái)越大?那么,為什么首先要不斷增加更大的cache呢?因?yàn)槊總€(gè)額外的內(nèi)存池都會(huì)推遲訪問(wèn)主內(nèi)存的需求,并且在特定情況下可以提高性能。
這張來(lái)自Anandtech的Haswell評(píng)論的圖表很有用,因?yàn)樗f(shuō)明了增加一個(gè)巨大的(128MB)L4 cache以及傳統(tǒng)的L1/L2/L3結(jié)構(gòu)對(duì)性能的影響。每個(gè)階梯代表一個(gè)新的cache級(jí)別。紅線是帶有L4的芯片。請(qǐng)注意,對(duì)于大文件,它的速度仍然幾乎是其他兩個(gè)Intel芯片的兩倍。
那么,將大量的片上資源用于cache似乎是合乎邏輯的。但事實(shí)證明,這樣做的邊際收益是遞減的。較大的cache既慢又貴。在每一位SRAM(6T)有六個(gè)晶體管,cache也很昂貴(就芯片尺寸而言,也就代表著成本)。過(guò)了某一點(diǎn),把芯片的功率預(yù)算和晶體管數(shù)量花在更多的執(zhí)行單元、更好的分支預(yù)測(cè)或額外的內(nèi)核上會(huì)更有意義。下圖是Pentium M(Centrino/Dothan)芯片,整個(gè)芯片的左側(cè)被用于一個(gè)巨大的L2 Cache。在過(guò)去單線程CPU的時(shí)代就是這樣,現(xiàn)在我們有了多核芯片和GPU,在很多情況下,整個(gè)CPU中用于cache的比例較小。
Cache設(shè)計(jì)如何影響性能
增加CPU cache對(duì)性能的影響與其效率或hit rate直接相關(guān);反復(fù)的cache miss會(huì)對(duì)CPU性能產(chǎn)生災(zāi)難性的影響。下面的例子雖然被大大簡(jiǎn)化了,但應(yīng)該可以說(shuō)明這個(gè)問(wèn)題。
想象一下,CPU必須連續(xù)100次從L1 cache加載數(shù)據(jù)。L1 cache的訪問(wèn)延遲為1ns,hit rate為100%。因此,CPU需要100ns的時(shí)間來(lái)執(zhí)行這個(gè)操作。
現(xiàn)在,假設(shè)cache有99%的hit rate,但CPU第100次訪問(wèn)實(shí)際需要的數(shù)據(jù)卻在L2中,有10-cycle(10ns)的訪問(wèn)延遲。這意味著CPU需要花99ns的時(shí)間來(lái)執(zhí)行前99次讀取,10ns的時(shí)間來(lái)執(zhí)行第100次。Hit rate降低1%,卻讓CPU的速度降低了10%。
在現(xiàn)實(shí)世界中,L1 cache的hit rate通常在95%到97%之間,但在我們的簡(jiǎn)單例子中,這兩個(gè)值對(duì)性能的影響不是2%,而是14%。請(qǐng)記住,我們假設(shè)丟失的數(shù)據(jù)總是在L2 cache中。如果數(shù)據(jù)已經(jīng)從cache中被驅(qū)逐位于主內(nèi)存中,訪問(wèn)延遲為80-120ns,那么95%和97%的hit rate之間的性能差異可能會(huì)使執(zhí)行代碼所需的總時(shí)間翻倍。
這張die shot,芯片中間的重復(fù)結(jié)構(gòu)是20MB的共享L3 cache。
早在人們對(duì)AMD的Bulldozer系列與Intel的處理器進(jìn)行比較時(shí),cache設(shè)計(jì)和性能影響的話題就出現(xiàn)了很多。目前還不清楚Bulldozer低迷的性能有多少可以歸咎于其cache子系統(tǒng),除了有相對(duì)較高的延遲外,Bulldozer系列還受到大量cache爭(zhēng)用的影響。如下圖所示,每個(gè)Bulldozer/Piledriver/Streamroller模塊共享其L1指令cache。
當(dāng)兩個(gè)不同的線程在同一內(nèi)存空間中寫入和覆蓋數(shù)據(jù)時(shí),cache會(huì)發(fā)生爭(zhēng)用現(xiàn)象。這損害了兩個(gè)線程的性能,每個(gè)核都被迫花時(shí)間把自己的首選數(shù)據(jù)寫進(jìn)L1,而另一個(gè)核卻迅速覆蓋了這些信息。即使AMD將L1代碼cache增加到96KB,并使其成為3-way associative,AMD的舊版Steamroller仍然被這個(gè)問(wèn)題所困擾。后來(lái)的Ryzen CPU沒有以這種方式共享cache,這個(gè)問(wèn)題也就沒再發(fā)生。
這張圖顯示了Opteron 6276(原Bulldozer處理器)的hit rate在兩個(gè)核都處于活動(dòng)狀態(tài)時(shí)是如何下降的,至少在一些測(cè)試中是這樣。然而,很明顯,cache的爭(zhēng)用并不是唯一的問(wèn)題,即使在兩個(gè)處理器的hit rate相同的情況下,6276在歷史上也很難超過(guò)6174的表現(xiàn)。
今天,Zen 2沒有這類弱點(diǎn),Zen和Zen 2的整體cache和內(nèi)存性能比老的Piledriver架構(gòu)好很多。
AMD最初的Ryzen首秀。Ryzen使用的cache系統(tǒng)與以前的AMD CPU非常不同。
現(xiàn)代CPU通常也有一個(gè)非常小的L0 cache,通常只有幾KB大小,用于存儲(chǔ)微操作。AMD和Intel都使用這種cache;Zen有一個(gè)2,048μOP的cache,而Zen 2有一個(gè)4,096μOP的cache。這些微小的cache pool的運(yùn)作原理與L1和L2相同,但代表一個(gè)更小的內(nèi)存池,CPU可以以比L1更低的延遲訪問(wèn)。通常情況下,公司會(huì)對(duì)這些能力進(jìn)行相互調(diào)整。Zen 1和Zen+(Ryzen 1xxx、2xxx、3xxx APU)有一個(gè)64KB的L1指令cache,是4-way set associative的,還有一個(gè)2,048μOP L0 cache。Zen 2(Ryzen 3xxx desktop CPU,Ryzen Mobile 4xxx)有一個(gè)32KB的L1指令cache,是8-way set associative的,有一個(gè)4,096µOP的cache。將set associativity和µOP cache的大小增加一倍,使AMD能夠?qū)1 cache的大小減少一半。這類權(quán)衡在CPU設(shè)計(jì)中很常見。
未來(lái)的創(chuàng)新
最近,IBM推出了Telum微處理器,cache結(jié)構(gòu)很有趣且不尋常。Telum有一般的L1和L2,但CPU沒有物理L3,而是部署了一個(gè)虛擬L3。下一代CPU不是完全驅(qū)逐CPU認(rèn)為不再需要的L2數(shù)據(jù),而是將其驅(qū)逐到同一硅片上不同CPU的L2 cache中,并將其標(biāo)記為L(zhǎng)3數(shù)據(jù)。每個(gè)核都有自己的32MB L2,整個(gè)芯片的虛擬L3是256MB。IBM甚至可以在多芯片系統(tǒng)中共享這種能力,創(chuàng)建一個(gè)虛擬的L4,總共有8192MB的數(shù)據(jù)存儲(chǔ)。
這種類型的虛擬cache系統(tǒng)是獨(dú)一無(wú)二的,它在x86方面沒有可對(duì)應(yīng),它是一個(gè)有趣的例子,說(shuō)明是如何推動(dòng)cache設(shè)計(jì)的極限。雖然AMD的V-Cache提供額外的L3,而不是L2,但我們完全沒有必要提及它。AMD 最近的成就以及有望在未來(lái) Zen CPU 上出現(xiàn)的功能是大型 L3 cache,垂直安裝在現(xiàn)有小芯片頂部,并通過(guò)芯片內(nèi)硅通孔連接到它們。Cache在這一點(diǎn)上可能已經(jīng)有40年的歷史了,但是制造商和設(shè)計(jì)師仍然在尋找方法來(lái)改進(jìn)并擴(kuò)大其實(shí)用性的方法。
緩存的發(fā)展
隨著研究人員不斷去尋找從較小的cache中擠出更高性能的方法,cache的結(jié)構(gòu)和設(shè)計(jì)仍在進(jìn)行微調(diào)。到目前為止,Intel和AMD還沒有大力推動(dòng)更大的cache,也沒有把設(shè)計(jì)一直擴(kuò)展到L4。有一些Intel的CPU帶有板載EDRAM,相當(dāng)于一個(gè)L4 cache,但這種方法并不常見。這就是為什么我們?cè)谏厦媸褂肏aswell的例子,盡管該CPU比較老。據(jù)推測(cè),對(duì)于大多數(shù)使用情況來(lái)說(shuō),大型L4 cache的優(yōu)勢(shì)性價(jià)比并不高。
不管怎么說(shuō),cache設(shè)計(jì)、功耗和性能對(duì)未來(lái)處理器的性能至關(guān)重要,任何一家公司如果可以在當(dāng)前設(shè)計(jì)的基礎(chǔ)上取得實(shí)質(zhì)性改進(jìn)都會(huì)獲得非常大的優(yōu)勢(shì)。
[參考文章]
How L1 and L2 Caches Work, and Why They're an Essential Part of Modern Chips — Joel Hruska