在計(jì)算機(jī)系統(tǒng)中,CPU高速緩存的作用
在計(jì)算機(jī)系統(tǒng)中,CPU高速緩存(英語:CPU Cache,在本文中簡稱緩存)是用于減少處理器訪問內(nèi)存所需平均時(shí)間的部件。在金字塔式存儲(chǔ)體系中它位于自頂向下的第二層,僅次于CPU寄存器。其容量遠(yuǎn)小于內(nèi)存,但速度卻可以接近處理器的頻率。當(dāng)處理器發(fā)出內(nèi)存訪問請求時(shí),會(huì)先查看緩存內(nèi)是否有請求數(shù)據(jù)。如果存在(命中),則不經(jīng)訪問內(nèi)存直接返回該數(shù)據(jù);如果不存在(失效),則要先把內(nèi)存中的相應(yīng)數(shù)據(jù)載入緩存,再將其返回處理器。緩存之所以有效,主要是因?yàn)槌绦蜻\(yùn)行時(shí)對內(nèi)存的訪問呈現(xiàn)局部性(Locality)特征。這種局部性既包括空間局部性(Spatial Locality),也包括時(shí)間局部性(Temporal Locality)。有效利用這種局部性,緩存可以達(dá)到極高的命中率。在處理器看來,緩存是一個(gè)透明部件。因此,程序員通常無法直接干預(yù)對緩存的操作。但是,確實(shí)可以根據(jù)緩存的特點(diǎn)對程序代碼實(shí)施特定優(yōu)化,從而更好地利用緩存。
我們知道計(jì)算機(jī)中為了平衡CPU的寄存器和內(nèi)存的速度差異,CPU 引入了高速緩存CPU Cache,前面我們介紹了什么是CPU Cache,以及CPU Cache的組織架構(gòu),本文我們來看看CPU Cache的是如何保證緩存一致性的?
系列文章:突破計(jì)算機(jī)性能瓶頸的利器CPU CacheCPU Cache是如何映射與尋址的?
單核CPU
在上一篇文章CPU Cache是如何映射與尋址的?中,我們介紹了CPU Cache的組織架構(gòu)及其進(jìn)行讀操作時(shí)的尋址方式,但是緩存不僅僅只有讀操作,還有寫操作,這會(huì)帶來一個(gè)新的問題:
當(dāng)CPU是單核的情況下,CPU執(zhí)行寫入數(shù)據(jù)操作,當(dāng)數(shù)據(jù)寫入CPU Cache之后,此時(shí)CPU Cache數(shù)據(jù)會(huì)和內(nèi)存數(shù)據(jù)就不一致了(這里前提條件:CPU Cache數(shù)據(jù)和內(nèi)存數(shù)據(jù)原本是一致的),那么如何保證Cache和內(nèi)存保持?jǐn)?shù)據(jù)一致?
主要有兩種寫入數(shù)據(jù)的策略:
Write Through寫直達(dá)
Write Back寫回
Write Through寫直達(dá)
Write Through寫直達(dá)是一個(gè)比較簡單的寫入策略,顧名思義就是每次CPU執(zhí)行寫操作,如果緩存命中,將數(shù)據(jù)更新到緩存,同時(shí)將數(shù)據(jù)更新到內(nèi)存中,來保證Cache 數(shù)據(jù)和內(nèi)存數(shù)據(jù)一致;如果緩存沒有命中,就直接更新內(nèi)存
這個(gè)策略優(yōu)點(diǎn)是簡單可靠,但是速度較慢,每次寫操作都需要與內(nèi)存接觸,此時(shí)緩存失去意義了,當(dāng)然讀操作時(shí)緩存還是能起作用的
Write Back寫回
Write Back寫回,也被稱為延遲寫入,相比于Write Through寫直達(dá)策略每次寫操作都需要內(nèi)存參與;而Write Back策略則是,CPU向緩存寫入數(shù)據(jù)時(shí),只是把更新的cache區(qū)標(biāo)記為dirty臟(即Cache Line增加 dirty臟 的標(biāo)記位 ** ),即來表示該Cache Line的數(shù)據(jù),和內(nèi)存中的數(shù)據(jù)是不一致的,并不同步寫入內(nèi)存**
也就是說對內(nèi)存的寫入操作會(huì)被推遲,直到當(dāng)這個(gè)Cache Line要被刷入新的數(shù)據(jù)時(shí),才將Cache Line的數(shù)據(jù)回寫到內(nèi)存中
如今CPU Cache更多地采用write back寫回的方式,寫回的核心就是盡可能減少回寫內(nèi)存的次數(shù),來提升CPU性能,缺點(diǎn)就是實(shí)現(xiàn)起來比較復(fù)雜
我們來看下它的具體流程是:當(dāng)CPU發(fā)起寫入操作請求時(shí),如果緩存命中,就直接更新 CPU Cache 里面的數(shù)據(jù),并把更新的Cache區(qū)標(biāo)記為dirty臟
若緩存未命中的話,再判斷緩存區(qū)已滿或者定位到的Cache Line已被占用,緩存就會(huì)執(zhí)行替換策略,常見的策略有:隨機(jī)替換RR、先進(jìn)先出FIFO、最近最少使用LRU等,我們后文再詳細(xì)介紹;
當(dāng)被替換的Cache Line被標(biāo)記為臟,也就是該Cache Line的數(shù)據(jù),和內(nèi)存中的數(shù)據(jù)是不一致的,此時(shí)會(huì)觸發(fā)操作:將Cache Line中的數(shù)據(jù)回寫到內(nèi)存中;然后,再把當(dāng)前要寫入的數(shù)據(jù),寫入到 Cache里,同時(shí)把Cache Line標(biāo)記成臟
如果Cache Line的數(shù)據(jù)沒有被標(biāo)記成臟的、緩存區(qū)未滿、定位到的Cache Line未被占用,那么直接把數(shù)據(jù)寫入到 Cache 里面,同時(shí)把Cache Line標(biāo)記成臟
隨機(jī)替換 (Random Replacement,RR) ,顧名思義就是隨機(jī)選擇被替換的緩存塊
實(shí)現(xiàn)簡單,在緩存大小較大時(shí)表現(xiàn)良好,能夠減少緩存替換的次數(shù),提高緩存命中率
但是沒有利用 “局部性原理”,無法提高緩存命中率;且算法性能不穩(wěn)定,在緩存大小較小時(shí),隨機(jī)替換可能導(dǎo)致頻繁的緩存替換,降低了緩存的命中率
FIFO
先進(jìn)先出(First-In-First-Out, FIFO),根據(jù)數(shù)據(jù)進(jìn)入緩存的順序,每次將最早進(jìn)入緩存的數(shù)據(jù)先出去,也就是先進(jìn)入緩存的數(shù)據(jù)先被淘汰。
實(shí)現(xiàn)簡單,適合短期的緩存數(shù)據(jù);但不合適長期存儲(chǔ)數(shù)據(jù)的場景,緩存中的數(shù)據(jù)可能早已經(jīng)過時(shí);當(dāng)緩存大小不足時(shí),容易產(chǎn)生替換過多的情況,從而降低了緩存的效率
FIFO 算法存在Belady貝萊迪現(xiàn)象:在某些情況下,緩存容量增大,命中率反而降低。概率比較小,但是危害是無限的
貝萊迪在1969年研究FIFO算法時(shí),發(fā)現(xiàn)了一個(gè)反例,使用4個(gè)頁框時(shí)的缺頁次數(shù)比3個(gè)頁框時(shí)的缺頁多,由于在同一時(shí)刻,使用4個(gè)頁框時(shí)緩存中保存的頁面并不完全包含使用3個(gè)頁框時(shí)保存的頁面,二者不是超集子集關(guān)系,造成都某些特殊的頁面請求序列,4個(gè)頁框命中率反而低
CPU緩存的容量比內(nèi)存小的多但是交換速度卻比內(nèi)存要快得多。緩存的出現(xiàn)主要是為了解決CPU運(yùn)算速度與內(nèi)存讀寫速度不匹配的矛盾,因?yàn)镃PU運(yùn)算速度要比內(nèi)存讀寫速度快很多,這樣會(huì)使CPU花費(fèi)很長時(shí)間等待數(shù)據(jù)到來或把數(shù)據(jù)寫入內(nèi)存?!?[1]緩存大小是CPU的重要指標(biāo)之一,而且緩存的結(jié)構(gòu)和大小對CPU速度的影響非常大,CPU內(nèi)緩存的運(yùn)行頻率極高,一般是和處理器同頻運(yùn)作,工作效率遠(yuǎn)遠(yuǎn)大于系統(tǒng)內(nèi)存和硬盤。實(shí)際工作時(shí),CPU往往需要重復(fù)讀取同樣的數(shù)據(jù)塊,而緩存容量的增大,可以大幅度提升CPU內(nèi)部讀取數(shù)據(jù)的命中率,而不用再到內(nèi)存或者硬盤上尋找,以此提高系統(tǒng)性能。但是從CPU芯片面積和成本的因素來考慮,緩存都很小。按照數(shù)據(jù)讀取順序和與CPU結(jié)合的緊密程度,CPU緩存可以分為一級(jí)緩存,二級(jí)緩存,部分高端CPU還具有三級(jí)緩存,每一級(jí)緩存中所儲(chǔ)存的全部數(shù)據(jù)都是下一級(jí)緩存的一部分,這三種緩存的技術(shù)難度和制造成本是相對遞減的,所以其容量也是相對遞增的。
當(dāng)CPU要讀取一個(gè)數(shù)據(jù)時(shí),首先從一級(jí)緩存中查找,如果沒有找到再從二級(jí)緩存中查找,如果還是沒有就從三級(jí)緩存或內(nèi)存中查找。一般來說,每級(jí)緩存的命中率大概都在80%左右,也就是說全部數(shù)據(jù)量的80%都可以在一級(jí)緩存中找到,只剩下20%的總數(shù)據(jù)量才需要從二級(jí)緩存、三級(jí)緩存或內(nèi)存中讀取,由此可見一級(jí)緩存是整個(gè)CPU緩存架構(gòu)中最為重要的部分。