為什麼在 CPU 中要用 Cache 從內存中快速提取數據?
如題,想問的是既然cpu速率高,從內存中讀取速度應該已經是內存的輸出上限了,那麼中間加一個cache作用是什麼?甚至還多了一步轉發的過程,為什麼能提高讀取速度呢?如果是預先讀取,為什麼cpu不能做呢?
題主把CPU與Cache分的太開了, Cache已經是現代CPU的一部分. 從內存的角度來看, Cache發來的讀數據請求就是CPU發來的讀數據請求. 實際上CPU所有關於Load和Store的請求, 都會由MOB(Memory Order Buffer) - L1D - L2 - L3 -DRAM這條路徑來完成, Cache只是這條路上的幾個驛站而已.
關於副標題內的疑問, 只用把問題邏輯順一下就解決了。
既然CPU速率高, 內存速率慢,那麼中間加一個Cache的目的就是為了讓存儲體系可以跟上CPU的速度.
普通的CPU+DRAM內存的結構, 如果沒有設計Cache, 每一次CPU都要找內存要數據, 這個延遲估計在80個時鐘周期左右. 這是因為CPU要從內部運算核心將請求發到CPU邊緣的匯流排上, 從匯流排上電路板, 到達北橋, 再上電路板到達DRAM. DRAM搜索到數據後如此再送回去. CPU動作那麼快, 等的黃花菜都涼了.如果加了Cache會怎樣? L1 Cache, 訪問延遲在4個周期左右, L2 Cache, 延遲在15個周期左右, L3Cache, 延遲在50個周期左右. 但是由於添加了很多Cache, CPU訪問內存的速度被降低了, 需要120個周期左右. 如果CPU需要的內容, 90%在L1 Cache里有, 6%在L2 Cache里有, 3%在L3 Cache里有, 1%要去找DRAM拿. 那麼整個存儲體系的等效延遲就是: 7.2個時鐘周期.
這不是爽歪了么??預先讀取,為什麼cpu不能做呢?
預取(prefetch)這件事cpu的確不做, 是Cache在做, 每一集的Cache都會有自己的prefetcher. 而實際上L1 Cache已經被融合進CPU內部里了, L1I和L1D和CPU流水線簡直就是緊挨在一起, L2 Cache又緊挨著CPU的L1D. 所以L1I, L1D, L2它們做預取, 和CPU自己做是一回事! 而且CPU跑多快, 預取的速度就有多快!上面憑什麼說"CPU需要的內容, 90%在L1 Cache里有, 6%在L2 Cache里有"? 就是因為Cache中數據大多是復用的, 而且Cache基於歷史數據還一直在預取! 而CPU和prefetcher像極了老總和小秘的關係, 比如:每次CPU缺什麼數據, 找內存拿了一次, 但是這被prefetcher記住了, 等一有空prefetcher就把頁(Page)中其他相關數據都從內存里拿出來. 這就等於把他七大姑八大姨街坊鄰居全叫了出來, CPU提取數據一般是有範圍的, 橫豎不超過這麼多, 所以CPU第二次再缺數據, 就不用去找內存了, 都在Cache里! 實際上Cache可以同時監控很多個頁, 這個過程反覆幾次, CPU就基本不再找內存要東西了.好吧,我找到了,答案如下:
程序運行情況表明,程序產生的地址往往集中在存儲器邏輯地址空間的很小範圍內,而指令通常又是順序執行,所以分布連續,再加上循環程序和子程序段都要運行多次,數據也是如此,這種現象稱為「程序訪問的局部性Locality of Reference」
cache將與當前指令集相關聯的一個不太大的後續指令集不斷的從內存儲器讀到cache,然後再向cpu高速傳送。
cpu在讀取指令或數據時,通常先訪問cache,若找到就直接讀入,成為「命中」,找不到則自己去存儲器查找「未命中」,讀到後也存入cache
cache容量超過一定值之後,命中率不再明顯增加。一般情況下使cache與內存的空間比為1:128,這種情況下,命中率一般在90%以上。
增加cache後cpu平均存取速度可以如下粗略計算:
平均存取速度 = cache存取速度x命中率+RAM存取速度x(1-命中率)至於為什麼不做到cpu中我想應該是為了可擴展性,內存將會越來越大,對應cache需要匹配,而cpu的更換速度會稍慢。計算機的存儲器結構大致是: CPU寄存器 ---緩存cache--存儲器(內存)--磁碟存儲(硬碟)。從左到又速度從快變慢,存儲大小由小變大。有了這個大致映象我們來回答這幾個問題:1.中間加一個cache作用是什麼?作用是加快CPU訪問常見數據的速度,經典的2/8理論在計算機體系中也是適用的,即20%的程序幹了80%的事情,所以cache做的事情是把內存裡面常用的存儲數據存在自己這裡供CPU讀取,因為cache的訪問延遲遠遠小於內存,所以訪問這部分存在cache里的數據就會比直接去訪問內存快的多,大概快一個量級。2.甚至還多了一步轉發的過程,為什麼能提高讀取速度呢?上面已經說過了因為cache的速度比內存快,我們又把常用的數據放到了cache裡面,那CPU訪問cache的速度當然比直接訪問內存快多了,就提高了讀取速度,其實更準確的說法是提高了帶寬。3.如果是預先讀取,為什麼cpu不能做呢?
預讀這個說法不能算錯,但也不是完全正確,至於為什麼不用CPU直接讀取,第一CPU的寄存器容量非常小,是Kb級別的,你讓他去訪問,內存,一次就這點,得多久才能把一個QQ那麼大的程序運行了。第二是CPU訪問內存,速度瓶頸自然在內存這裡,那CPU當然訪問cache更快了,而且現在的cache分L1 L2 L3這幾層,從左到又速度從快變慢,存儲大小由小變大。
前面大家回答的非常好,直接命中要害——內存太慢還有提高帶寬等等。不知道題主對處理器研究多深,就按照自己旁聽過一門課的水平來回答,只能補充一下為什麼內存這麼慢,以及一些cache相關的優化。
CPU的設計,不是一下子出現的,很多都是出現問題然後解決問題,再出現問題解決問題的過程。cache設計不只是cache緩存,還有很多具體技術,比如L1,L2,比如多頁,DMA等等。首先理解普通PC機工作:從內存讀取一條指令到CPU,CPU執行,根據需要,CPU寫內部寄存器或者內存。比如我們自己編寫的程序,不論是hello world還是web server或者LOL,都是可以認為是回寫內存。操作系統(內核和驅動)除了回寫內存之外,還有很大的工作是寫內部寄存器,比如是寫串口,寫顯示器,寫網口,寫硬碟介面等等。
以上都不用管,只需要理解用戶程序就是讀寫內存。CPU執行一般都是「從內存讀取指令」「執行指令」「按需要回寫或不回寫內存」。
為了不使用公式,這裡以某筆記本為例使用一些數字,CPU時鐘頻率2GHz,一條指令的執行需要假設在0.5ns到20ns之間(具體數據沒查詢,這個20ns也是按照古老的CPU的乘法指令來的),那麼特殊情況下,0.5ns之後就需要下一條指令了。
內存匯流排頻率1.366GHz,那麼讀取一個內存地址,也許需要2ns(CPU寫地址線,內存觸發數據線,CPU鎖存數據等等步驟)。- 問題一、CPU花費2ns讀取一條指令,0.5ns執行,2ns回寫內存,然後讀取下一條。平均0.5ns的指令,花費4.5ns。
方案:流水線。
1. CPU內部的流水線壓縮平均指令執行時間,比如x86的微指令之類,這個屬於更廣泛的CPU架構部分的內容了。2. 「預先讀取內存」。CPU執行的那個0.5ns,CPU同時可以開始讀取下一條指令,0.5ns之後,內存匯流排仍然在讀取,還不能回寫內存,等待1.5ns。這樣,平均0.5ns的指令,耗費4ns。如果該指令不會寫內存,那麼平均0.5ns的指令,耗費2ns。平均2ns的指令,耗費2ns,平均20ns的指令,耗費20ns。統計當前世界上常用指令的耗費時間,可以看到優化的效果了。 - 問題二、大多數指令已經被優化到了0.5ns了,內存還是太慢,加上還有很多指令需要回寫內存,效率還是太低。方案:cache。cache是CPU內部的存儲空間,讀取速度和時鐘頻率一樣快,0.5ns。cache單獨的控制單元,與CPU的執行部分並行。
在有些20ns的指令時候,多讀取一些指令緩存下來。回寫內存時候,也是先寫到cache上,等到內存匯流排空閑時候再回寫內存上面。這樣充分利用一些耗時CPU操作,這個在早期一些CISC的CPU有一定用處。
如果cache上的數據需要在下一條指令使用,那麼直接讀取cache,這樣原本寫-讀-寫-讀的重複對於一個地址的操作就被壓縮到2ns,這樣很多個0.5ns的指令時間,只需要一個2ns的讀寫內存,這樣達到內存匯流排的最大利用。在真實世界上,這種操作是很多的。 - 方案:cache的DMA讀取內存,0.8ns寫地址到內存匯流排,然後內存不停寫內存數據匯流排,這樣達到平均0.8ns就能讀取到指令。DMA寫內存也是一樣,壓縮到平均0.8ns。
- 方案:DDR內存雙通道、提高內存匯流排頻率等等。
- 問題三、if else分支goto跳轉之類,打破流水線(比如當年頻率大戰時候奔騰4的恐怖的四十五級流水線),同時cache都是連續讀取的內存數據,裡面沒有goto到的很遠的內存地址的數據。方案:cache分頁以及分支預判。cache讀取了一些的數據,在讀取的時候,發現有分支,那麼添加一個cache緩存分支的地址數據,這樣不論if else goto要使用哪一個分支的內存數據,都已經放到cache裡面了。由於一段代碼裡面可能有很多分支,那麼就需要預先讀取很多分支到cache。這裡分頁大小,是根據真實世界中的大多數程序的統計來定的。cache當然越大越好,但是cache單byte成本很高,而且良品率等原因,cache總體大小有限。分頁太大,頁數不夠,無法存儲足夠的分支;分頁太小,頁數太多cache切換耗時,當然還有其它的各種原因。分支預判這裡還會有一個命中率的問題,就是如果一段代碼裡面很多分支,超過了頁數,那麼就有一個哪些分支概率低,哪些分支概率高的問題,這些就需要真實世界統計了,也是一個優化。
- 問題四、cache還是太貴,怎樣保證成本的情況下,做大cache?方案:L1,L2乃至L3。做一些成本低的,速度可以慢一點的,但是更大的cache。這樣L1cache預判失敗之後,便宜的更大的L2可能預判成功。這個也算是提高命中率。
======================
那麼,如果內存讀寫速度和CPU一樣快,是不是就不需要cache了呢?是!但是,CPU內部匯流排距離短,CPU到內存匯流排長,並且加上觸點、焊點等因素,內存匯流排追不上CPU內部匯流排速度。
硬碟的cache是怎麼回事?類似,硬碟匯流排讀寫硬碟的速度,快於硬碟讀寫碟片的速度。(CPU不直接讀寫硬碟)估計你把cpu硬體的cache 和操作系統的內存區cache弄混了,
比如題主要寫一篇論文,寫作過程中需要用到一大堆參考書籍,那麼題主怎麼辦?
有三種辦法可以解決這個問題。
普通青年:去圖書館借來幾十本和論文相關的書籍放在自己房間的書架上,然後再挑選幾本重點的放在自己的桌子上。接著打開電腦開始寫論文。最後,寫論文大約花了六個月,其中跑了好幾次圖書館,換了好幾批書。文藝青年:什麼書架什麼桌子,統統不要。每次寫論文需要參考書,就跑去圖書館借一本來,然後寫兩句,發現需要下一本了,跑去圖書館再借一本;又寫了三句發現還需要一本,就再去圖書館借一本來……最後,花了十年時間終於把論文寫好了!附帶還減肥二十公斤,練出了一雙修長的小腿!二逼青年:先買一個幾千平米的展覽大廳,然後斥巨資買了一張巨大無比的桌子,然後將所有可能用的,可能用不到的參考書全部買了回來堆在桌子上,去TMD圖書館和書架,老子想要啥隨手就拿,有錢就是這麼任性!由於不用跑圖書館了,寫論文的時間「大大」縮短了,大概只要四個半月就寫完了。耗資兩個億節省了一個半月時間,划算吧?那麼現在問題來了:緩存技術哪家強?簡單而言,cache是用SRAM做的,內存是用DRAM做的,SRAM比DRAM快了好多倍。
使用容量小的SRAM作為容量大的DRAM的cache可以:
獲得當前最昂貴技術所能達到的最快訪問速度,以及當前最廉價技術所能達到的最大存儲容量。
這也是存儲層次的核心思想,也因此我們有了訪問速度依次下降而存儲容量依次提高,價格依次下降的存儲層次體系:
CPU寄存器,L1、L2、L3cache,內存,磁碟,遠程存儲(網路)1,內存太慢了。2,如果想讓CPU具有預讀取功能,那讀出來的東西放哪?Cache里。3,乾脆把預讀的活也讓Cache幹了吧。4,於是有了Cache,進一步分化為3級。
相當於在倉庫和超市中間建立多個小倉庫,這樣子貨物可以一批批的運到超市,
就是超市賣完貨物後可以直接從附近的小倉庫調貨,而不是從遙遠的大倉庫調貨
如果沒有小倉庫的存在的話,超市的容量有限,只能買完之後再從大倉庫調貨。
說白了就是縮短了CPU 的等待時間,使效率更高。
我覺得我解釋的不生動╮(╯▽╰)╭
這樣,再來個例子,CPU 今天需要解決五件事,簡稱
一,二,三,四,五如果沒有高速緩存存儲器(cache )的話那就是,先解決一,一完事了,二再過去,二完事了,三再過去…………
如果有的話,現在假設CPU 和內存中加了一個cache, 那麼先解決一,解決一的過程中二到了cache, 等一解決了,二就能直接從cache 到CPU ,這樣二到CPU 的時間就被縮短,因為邏輯上距離被縮短…………現在好像cache 還可以設置多級,就是一個又一個中途休息的倉房……
這樣是不是好了一點?首先在計算機系統中,cpu的速度,大於cache速度,大於內存的速度。cpu要從存儲設備(cache或者內存)上讀取(寫入)指令或者數據,這就遇到一個問題,cpu處理速度和存儲的讀取數據不匹配,比如,一個單位的數據,cpu用一個時間單位處理完畢,但從存儲設備讀進cpu需要100個時間單位。為了解決這個問題怎麼辦?計算機科學家前輩們發現,cpu要處理的數據一般都會集中在內存的某一段地址範圍內,這樣就產生了一種做法,將內存中的數據放入cache中,cpu讀數據,可以先從cache中尋找,假設cpu從cache中讀取數據需要10個時間單位,而從內存中讀取需要100個時間單位,這就節省了90個時間單位,當然,前提是在cache中可以找到數據。如果在cache中找不到,大不了再跑內存中取找。
這種問題隨便一本計算機組成原理的書就知道了
推薦閱讀:
※怎樣減緩電腦變卡的速度?
※為什麼某寶上512GB的m.2和sata3介面的SSD價格一樣呢?
※平面設計用電腦,這個配置如何?
※如何評價齊河一家的文章《不知廉恥作小人是否能在網上翻雲覆雨》?
※現代( HYNIX)內存上的標記「2GB 2R*8 PC3-10600E-9-10-E0」「HMT125U7TFR8C-H9 T0 AB-C 1117」 都是什麼含義?內存擴容時在兼容性方面要匹配哪些參數?