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