半夜,滴滴司機(jī)問(wèn)我會(huì)LRU嗎?
1
宮本走出公司的時(shí)候,已經(jīng)將近半夜。此時(shí)天上的月亮仍舊散發(fā)著清冷的幽光,無(wú)情地審視著大地。
最近公司業(yè)務(wù)繁忙,大批技術(shù)人員都被迫加班到很晚。宮本正是這些技術(shù)人員中的一份子,從他開(kāi)始寫(xiě)代碼到如今,已經(jīng)將近五年。
「需求根本做不完,這幾天連續(xù)加班要吐了?!箤m本小聲嘟囔了一句,掏出手機(jī)準(zhǔn)備叫個(gè)網(wǎng)約車。
宮本所在的公司是互聯(lián)網(wǎng)行業(yè),號(hào)稱是行業(yè)內(nèi)發(fā)展迅猛的獨(dú)角獸。但是宮本在其中工作得并不順心;一方面是由于技術(shù)工作的壓力太大,二來(lái)也是因?yàn)楣疽?guī)模比較大,個(gè)人的成就感無(wú)法得到充分的滿足。
半夜的網(wǎng)約車基本不用排隊(duì),不到五分鐘,一輛黑色的吉利帝豪便沿著定位開(kāi)到了公司大門(mén)。一上車,宮本就從背包中掏出了筆記本電腦,打算利用路上的時(shí)間再補(bǔ)補(bǔ)技術(shù)基礎(chǔ)。
打開(kāi)筆記本,內(nèi)嵌的鍵盤(pán)后背燈和屏幕同時(shí)亮了起來(lái),照亮了宮本有點(diǎn)疲倦的臉龐。屏幕上開(kāi)著一個(gè)網(wǎng)頁(yè),顯示的是「CPU緩存」之類的字樣,底下還配有長(zhǎng)段的圖文解析。
關(guān)于CPU 緩存的相關(guān)知識(shí),宮本早在大學(xué)期間就已經(jīng)學(xué)過(guò)。只不過(guò)年代久遠(yuǎn)加上也沒(méi)有時(shí)?;仡?,現(xiàn)在也忘得差不多了。這回是打算將計(jì)算機(jī)組成的基礎(chǔ)知識(shí)再溫習(xí)一遍,以應(yīng)對(duì)之后可能的跳槽。
「CPU緩存相關(guān)的知識(shí),重點(diǎn)應(yīng)該在于計(jì)算機(jī)存儲(chǔ)系統(tǒng)的層次結(jié)構(gòu)、地址映像方法和緩存替換算法之類的吧。」宮本低頭喃喃自語(yǔ)道,卻沒(méi)注意到前方的司機(jī)微微瞟了一眼后視鏡。
說(shuō)回來(lái),宮本自上車起注意力就沒(méi)落在司機(jī)上,心思還沒(méi)從工作狀態(tài)中緩過(guò)來(lái)。事實(shí)上,司機(jī)外形跟宮本倒有些相似,只不過(guò)看起來(lái)年紀(jì)更大一些,大概35左右。同時(shí)若隱若現(xiàn)的發(fā)際線都無(wú)意間展露出中年人的危機(jī)。
只不過(guò)宮本也無(wú)暇顧及前方這個(gè)與自己有些神似的男人了,一頭撲進(jìn)了學(xué)習(xí)中。
2
CPU 緩存「Cache」指的訪問(wèn)速度比一般內(nèi)存快得多的高速存儲(chǔ)器,主要是為了解決 CPU 運(yùn)算速率與內(nèi)存讀寫(xiě)速率不匹配的問(wèn)題。因?yàn)?CPU 的運(yùn)算速率比內(nèi)存讀寫(xiě)速率快得多,當(dāng) CPU 需要向內(nèi)存請(qǐng)求數(shù)據(jù)或者寫(xiě)入數(shù)據(jù)時(shí),就需要一直等待內(nèi)存緩慢的讀寫(xiě)。在這個(gè)過(guò)程中,CPU 的高速運(yùn)算能力就無(wú)法得到充分發(fā)揮。
「所以緩存的作用就像是 CPU 和內(nèi)存之間進(jìn)行數(shù)據(jù)緩沖的橋梁?!箤m本若有所思。
緩存中的數(shù)據(jù)是內(nèi)存中的一部分,這一部分?jǐn)?shù)據(jù)被認(rèn)為是 CPU 在短時(shí)間內(nèi)會(huì)即將訪問(wèn)到的數(shù)據(jù)。當(dāng) CPU 在調(diào)用數(shù)據(jù)時(shí),會(huì)先從緩存中調(diào)用,而不直接通過(guò)內(nèi)存。當(dāng)在緩存中找到想要的數(shù)據(jù)時(shí),就會(huì)立即讀取并返回給 CPU 處理;如果沒(méi)有找到,就以相對(duì)較慢的速度從內(nèi)存中讀取,同時(shí)將這個(gè)數(shù)據(jù)所在的數(shù)據(jù)塊都調(diào)入緩存中,方便下次對(duì)該數(shù)據(jù)塊的讀取。
「這樣可行主要還是因?yàn)榫植啃栽戆??!箤m本漸漸找回了上大學(xué)時(shí)的記憶。他記得程序在運(yùn)行時(shí)對(duì)內(nèi)存的訪問(wèn)會(huì)呈現(xiàn)出局部性的特征,這種特征表現(xiàn)在使用了某一個(gè)數(shù)據(jù)時(shí),往往該數(shù)據(jù)附近的數(shù)據(jù)會(huì)有更高的概率在下次被使用。
「那緩存是如何發(fā)揮作用的呢?」宮本有些不太記得緩存的組成,埋頭繼續(xù)研究。前座的司機(jī)時(shí)不時(shí)通過(guò)后視鏡瞥一瞥鉆心學(xué)習(xí)的宮本,不經(jīng)意間眼神里流露出一種夾雜著無(wú)奈和釋然的復(fù)雜神情。
首先來(lái)講講計(jì)算機(jī)存儲(chǔ)系統(tǒng)的層次結(jié)構(gòu)。一般而言,通用計(jì)算機(jī)的存儲(chǔ)層級(jí)分為四層,分別為 CPU 內(nèi)部寄存器、高速緩存、主存儲(chǔ)器和輔存儲(chǔ)器。主存可以看作是一般而言的內(nèi)存,而輔存又可根據(jù)是否與計(jì)算機(jī)相連分為聯(lián)機(jī)和脫機(jī)兩種類型。
計(jì)算機(jī)存儲(chǔ)系統(tǒng)的層次結(jié)構(gòu)
從層次結(jié)構(gòu)上可以看出,高速緩存處于第二層次,起到承上啟下的作用。而為了能夠與 CPU 進(jìn)行高速交互,同時(shí)與主存進(jìn)行數(shù)據(jù)的交換,高速緩存的結(jié)構(gòu)也十分具有個(gè)人特色。
高速緩存并不是一中概念上的緩存,而是由特定 SRAM 組成的物理芯片。在現(xiàn)代 CPU 中,大量的空間都已經(jīng)被 SRAM 占據(jù)。下圖是一張Intel CPU的放大圖片,紅色框標(biāo)出的就是其中一部分高速緩存。
SRAM:SRAM是指靜態(tài)隨機(jī)存儲(chǔ)器,它具有靜止存取的功能,也就是可以不需要刷新電路就保存內(nèi)部的數(shù)據(jù)。性能高,功耗小,速度快,價(jià)格高。
Intel CPU,圖源網(wǎng)絡(luò),侵刪
高速緩存一般由兩部分組成,控制部分和存儲(chǔ)器部分??刂撇糠质怯脕?lái)判斷 CPU 所請(qǐng)求的數(shù)據(jù)是否保存在存儲(chǔ)器中,如果在,則稱為命中;若不在則沒(méi)有命中。
CPU高速緩存組成
當(dāng) CPU 命中緩存時(shí),即可直接對(duì)高速緩存的存儲(chǔ)器進(jìn)行尋址;未命中時(shí),則需要根據(jù)緩存替換算法將主存中的數(shù)據(jù)塊替換到高速緩存的存儲(chǔ)器中。
3
「接下來(lái)是地址映像方法了吧?!箤m本還沒(méi)從緩存的組成結(jié)構(gòu)中緩過(guò)神來(lái),就聽(tīng)見(jiàn)前座傳來(lái)一聲滄桑的話語(yǔ)。
「誒師傅,行家啊!」宮本驚訝的抬起頭,正好對(duì)上后視鏡中那雙炯炯有神的目光。原來(lái)是宮本在學(xué)習(xí)時(shí)不自覺(jué)地自言自語(yǔ)起來(lái),引起了司機(jī)師傅的注意。
「哈哈哈,早年學(xué)過(guò),忘得差不多了?!顾緳C(jī)師傅靦腆一笑。宮本心里一驚,沒(méi)想到真是全民學(xué)編程的時(shí)代,高手無(wú)處不在。
「那您也太厲害了,我正準(zhǔn)備了解下高速緩存中的地址映像方法呢。」宮本贊嘆道。
「我之前還在當(dāng)程序員的時(shí)候,就經(jīng)常被拉去當(dāng)面試官。關(guān)于地址映像方法啊,頁(yè)面置換算法啊之類的問(wèn)題基本上是必問(wèn)的問(wèn)題了。這也是對(duì)于計(jì)算機(jī)組成原理的基本考察。」司機(jī)師傅仿佛打開(kāi)了話匣子。
「那您這功力很深厚呀,這么多年了還記得這么基礎(chǔ)的東西。」宮本沒(méi)想到這位師傅原來(lái)還是一位資深的程序員,時(shí)間過(guò)去這么久依然記得高速緩存的一些技術(shù)重點(diǎn)。
「其實(shí)也還好,這種基礎(chǔ)的知識(shí)雖然實(shí)際工作中不會(huì)直接用到,但是對(duì)于理解代碼還是有輔助作用的。只不過(guò)現(xiàn)在很多年輕人都比較忽視這方面的學(xué)習(xí)?!顾緳C(jī)師傅略帶惋惜的說(shuō)道。宮本聽(tīng)完表示贊同的一笑,也沒(méi)有接話,繼續(xù)沉迷自己學(xué)習(xí)中去了。
的確也是,現(xiàn)在許多年輕人都是為了編程而編程,反而忽視了許多計(jì)算機(jī)基本的常識(shí)和基本思想。估計(jì)很多人可能都還不知道高速緩存中有哪些地址映像方法。
實(shí)際上地址映像方法就是為了將主存地址與高速緩存中存儲(chǔ)器的地址對(duì)應(yīng)起來(lái),進(jìn)行地址的映射,這樣 CPU 在工作才能通過(guò)緩存正確地對(duì)主存數(shù)據(jù)進(jìn)行快速讀寫(xiě)。
地址映像方法有三種,直接映像,全相聯(lián)映像和組相聯(lián)映像。
直接映像
直接映像的圖示如下,主存單元中的區(qū)塊與緩存中內(nèi)存塊的關(guān)系是固定的,主存中的內(nèi)存塊只會(huì)存放在高速緩存存儲(chǔ)器中的相同塊號(hào)。因此,只要主存地址中的主存區(qū)號(hào)與緩存中的主存區(qū)號(hào)相同,則表明訪問(wèn)緩存命中。
這樣一來(lái),根據(jù)主存地址中的區(qū)內(nèi)塊號(hào),就可以得到需要訪問(wèn)的高速緩存存儲(chǔ)器中塊號(hào),從而即可從緩存中訪問(wèn)需要的數(shù)據(jù)。
直接映像帶來(lái)的好處很明顯, 地址變換很簡(jiǎn)單粗暴,主存的內(nèi)存塊與緩存直接映射,一整塊進(jìn)行對(duì)應(yīng)。這樣的方式雖然簡(jiǎn)單,但是靈活性很差。主存中不同區(qū),但是塊號(hào)相同的內(nèi)存塊不能同時(shí)被調(diào)入緩存存儲(chǔ)器中。并且,當(dāng)緩存存儲(chǔ)器中有空著的塊也無(wú)法被主存中其它的內(nèi)存塊替換。
直接映像方式
全相聯(lián)映像
為了解決直接映射造成靈活性差,緩存空間無(wú)法充分利用的問(wèn)題,全相聯(lián)映像的方式被提出來(lái)。全相聯(lián)與直接映像就是兩個(gè)極端,一個(gè)只能整個(gè)區(qū)塊進(jìn)行對(duì)應(yīng),一個(gè)就允許任意主存的塊調(diào)入高速緩存存儲(chǔ)器中任意的塊。
全相聯(lián)映像方式
在進(jìn)行地址變換時(shí),當(dāng)主存地址高位的主存塊號(hào)與高速緩存中中主存塊號(hào)相比時(shí),有相同的塊號(hào)即表示命中。一旦命中,CPU 即可通過(guò)緩存存儲(chǔ)器中的塊內(nèi)地址訪問(wèn)到相應(yīng)的數(shù)據(jù)。
全相聯(lián)映像能夠提供非常靈活的變換方式,不受主存所在塊的限制。但是同樣也是由于過(guò)于靈活,導(dǎo)致實(shí)際在變換的時(shí)候,無(wú)法從主存塊號(hào)直接獲得高速緩存存儲(chǔ)器的塊號(hào),變換過(guò)程相對(duì)比較復(fù)雜,速度也比較慢。
組相連映像
既然兩者方法各有利弊,不妨我們就折中一下。因而有了中庸的組相連映像方式。
組相連方式就是將主存和高速緩存存儲(chǔ)器中的塊再分成組,組之間采用直接映像方式,而組內(nèi)的塊則采用全相聯(lián)映像方式。具體的實(shí)現(xiàn)可以參考以下圖示。
舉例來(lái)說(shuō),主存任何區(qū)的0組只能存到高速緩存中的0組中,1組只能存到1組。這就是所謂組間的直接映像。而主存相同一組的任意一塊可以存入高速緩存相同組中的任意一塊。這就是所謂組內(nèi)的全相聯(lián)方式。
組相連映像方式
在進(jìn)行地址變換時(shí),可通過(guò)直接映像方式來(lái)決定組號(hào),在一組內(nèi)再用全相聯(lián)映像方式?jīng)Q定高速緩存中的塊號(hào)。通過(guò)比較主存地址高位決定的主存區(qū)號(hào)與緩存中的區(qū)號(hào),即可決定是否命中。
4
司機(jī)師傅見(jiàn)宮本專心思考去了,也沒(méi)有強(qiáng)行打擾,穩(wěn)穩(wěn)地握著方向盤(pán),眼光眺向遠(yuǎn)方。
「這地址映像方法還挺有意思,簡(jiǎn)單的地址映射也能根據(jù)具體的情況進(jìn)行整體和局部的優(yōu)化?!共灰粫?huì),宮本抬起頭,微微感嘆了一聲。
「哈哈哈,說(shuō)的是啊。計(jì)算機(jī)領(lǐng)域很多看起來(lái)想當(dāng)然的東西都是經(jīng)過(guò)了不同程度的優(yōu)化,才能真正運(yùn)用在實(shí)際的系統(tǒng)中?!顾緳C(jī)師傅聽(tīng)見(jiàn)宮本的感嘆,接上了話茬。
「您想必之前是個(gè)很純粹的技術(shù)人吧?!箤m本對(duì)這個(gè)看起來(lái)普普通通的司機(jī)師傅充滿了好奇,感覺(jué)像是個(gè)世外高人,大隱隱于市般。
「噗,這哪談得上。不然也不會(huì)出來(lái)跑滴滴了。只是之前工作的時(shí)候比較看重基礎(chǔ)吧。」司機(jī)師傅笑了一聲。
「不過(guò),如果我是你的面試官,我可能會(huì)更喜歡問(wèn)你緩存替換算法。地址變換這些東西沒(méi)啥技術(shù)含量,對(duì)程序員來(lái)說(shuō)也并不是那么透明。相對(duì)來(lái)說(shuō)替換算法的思想更值得你們學(xué)習(xí)哈。比方說(shuō) LRU」司機(jī)師傅話題一轉(zhuǎn),有了那么點(diǎn)面試官的味道。想必應(yīng)該也是直男一個(gè)。
「哈是的,我正準(zhǔn)備看呢。我大概記得應(yīng)該有好幾種吧,除了 LRU ,還有比如隨機(jī)替換、FIFO之類的。」宮本之前也經(jīng)過(guò)過(guò)幾次面試,對(duì)司機(jī)師傅的說(shuō)法表示贊同。
「那你好好看看?!顾緳C(jī)師傅建議道,說(shuō)完二人也都沒(méi)有再說(shuō)話了。
緩存替換算法的目的很明顯,就是為了使得高速緩存獲得盡可能高的命中率,當(dāng)緩存的存儲(chǔ)器滿了的時(shí)候,將不用的數(shù)據(jù)塊進(jìn)行刪除,替換新的數(shù)據(jù)。常用的替換算法有以下幾種:
- 隨機(jī)替換算法:顧名思義,就是通過(guò)隨機(jī)獲得一個(gè)需要被替換的塊號(hào),并用新的數(shù)據(jù)替換該塊。
- 先進(jìn)先出算法:即FIFO,通過(guò)緩存中的塊進(jìn)入隊(duì)列的先后順序進(jìn)行淘汰和替換,先進(jìn)入緩存的數(shù)據(jù)塊最先被替換。
- 最近最少使用算法:即LRU,將近期最少使用的緩存塊替換出去。這種算法在實(shí)現(xiàn)的時(shí)候?qū)⒆罱褂玫牡臄?shù)據(jù)塊放置到靠近緩存頂部的位置。每一次替換都從緩存尾部開(kāi)始進(jìn)行。
- 最不經(jīng)常使用算法:即LFU,這個(gè)算法需要記錄每一個(gè)緩存塊被訪問(wèn)的頻率,每一次替換都從最低訪問(wèn)頻率的數(shù)據(jù)塊開(kāi)始。
- 最近最常使用算法,即MRU,這個(gè)算法會(huì)最先移除最近最常使用的數(shù)據(jù)塊。
替換算法說(shuō)白了,就是看采用怎么樣的策略將緩存中的數(shù)據(jù)塊替換出去。在實(shí)際的應(yīng)用中,還會(huì)根據(jù)程序具體的情況對(duì)不同的算法進(jìn)行優(yōu)化選擇。
5
看到這,宮本對(duì) CPU 高速緩存的概念已經(jīng)有了比較清晰的了解。再次抬起頭,發(fā)現(xiàn)已經(jīng)能夠看到小區(qū)聳立的高樓。一棟棟樓盤(pán),亮著燈的已經(jīng)不多。
「師傅,我快到加了,這回感謝你哈。沒(méi)想到打車也能遇到同行哈哈?!箍赐昃彺妫瑢m本松了口氣,看來(lái)下班回家的時(shí)間還是能夠利用起來(lái)的。
「不過(guò)我還是想問(wèn)一下,您當(dāng)初為啥不干這行了呢?」一直懷著這樣的疑問(wèn),宮本還是忍不住問(wèn)了出來(lái)。
「我啊,其實(shí)也沒(méi)為啥吧。之前當(dāng)程序員的時(shí)候,雖然賺得挺多的,但是累是真的累。很長(zhǎng)一段時(shí)間也找不到自己成長(zhǎng)的方向,在公司工作的時(shí)間越來(lái)越長(zhǎng),卻感覺(jué)已經(jīng)少了那股跟新人一樣的活力和朝氣。怎么說(shuō)呢,就像是為了工作而工作?!?/p>
「所以您就不干啦?」
「倒也沒(méi)有那么果斷吧,糾結(jié)了挺長(zhǎng)時(shí)間的。你別看我現(xiàn)在在開(kāi)滴滴,其實(shí)這只不過(guò)是我目前的副業(yè)?!?/p>
「那你現(xiàn)在還敲代碼嗎?」
「現(xiàn)在還是天天敲鍵盤(pán),只不過(guò)不是敲代碼啦。我開(kāi)滴滴也就在你們公司這附近接單,主要是為了找找以前的感覺(jué),同樣也是找找靈感吧?!?/p>
「哇,那您應(yīng)該財(cái)富自由了吧哈哈?!?/p>
「哈哈哈,還行~」
小區(qū)到了,宮本輕松的走下了車,并再次跟司機(jī)師傅道了聲謝謝。短短的幾十分鐘的車程,讓他收獲滿滿。
不僅對(duì) CPU 緩存原理進(jìn)行了快速的復(fù)習(xí),還有幸遇到了別樣的人生。他也不清楚自己是否能夠邁過(guò)35歲這道坎,但至少情況可能沒(méi)那么糟糕。就像那位司機(jī)師傅一樣,大膽的嘗試加上勇敢的付出,或許也能夠成就別樣的人生。
大家猜猜司機(jī)師傅現(xiàn)在的主業(yè)是什么呢?
這篇文章也是一個(gè)大膽的嘗試呢,感覺(jué)純粹的技術(shù)文章可能太過(guò)枯燥了。所以給這篇枯燥的技術(shù)套上了一個(gè)故事的場(chǎng)景,實(shí)際上對(duì)技術(shù)點(diǎn)本身沒(méi)啥影響。
本文轉(zhuǎn)載自微信公眾號(hào)「業(yè)余碼農(nóng)」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系 業(yè)余碼農(nóng)公眾號(hào)。