聽說你只知內存,而不知緩存?CPU表示很傷心

一般我們的開發同學們都知道自己機器的CPU是幾核、內存是多大。但是對於CPU內部對程序性能影響較大的緩存卻是一知半解。有些開發同學都是計算機的緩存有L1、L2、L3,但是再詳細一點的問題,可能就很少有同學能答的完整了。如果下面這幾個問題你能脫口而出,請跳過本節。例如:

  • 緩存究竟在哪裡?
  • L1有幾種?
  • 你的緩存有幾級,分別是多大?
  • 你的24核的機器,一二三級緩存分別有幾個,存在共享的情況嗎?

其實緩存對計算機程序運行性能影響極大,但是他們在開發同學心目中的存在感卻不如內存高。要知道CPU緩存以及緩存算法的設計是現代CPU設計的核心任務之一。飛哥覺得緩存們一定感到很傷心。

Intel CPU體系結構

其實在286之前的時代的CPU本是沒有緩存的,因為當時的CPU和內存速度差異沒有現在這麼大,CPU直接訪問內存。但是到386時代,CPU和內存的速度不匹配了,第一次出現了緩存。而且最早的緩存並沒有放在CPU模塊裡,而是放在主板上的。再往後CPU越來越快,現在CPU的速度比內存要快百倍以上,所以就逐步演化出了L1、L2、L3三級緩存結構,而且都集成到的CPU芯片裡,以進一步提高訪問速度。

我們來看下現代Intel的CPU架構的基本結構。


聽說你只知內存,而不知緩存?CPU表示很傷心


圖1.png

L1最接近於CPU,速度也最快,但是容量最小。一般現代CPU的L1會分成兩個,一個用來cache data,一個用來cache code,這是因為code和data的更新策略並不相同,而且因為CISC的變長指令,code cache要做特殊優化。 一般每個核都有自己獨立的data L1和code L1。

越往下,速度越慢,容量越大。L2一般也可以做到每個核一個獨立的。但是L3一般就是整顆CPU共享的了。

UEFIBlog裡提供了一個比較好的物理解剖圖,比較好地展示了出來:


聽說你只知內存,而不知緩存?CPU表示很傷心


圖2.jpg

實際查看

上面介紹的只是籠統的概念。但是每個CPU的緩存都是不一樣的,而且“紙上得來終覺淺”,我覺得我們還是有必要進行下一步的實機勘探工作。

Linux的內核的開發者定義了一套框架模型來完成這一目的,它就是CPUFreq系統。

CPUFreq提供的sysfs接口,可以讓我們看到比/proc/cpuinfo更為詳細的CPU詳細信息。

# cd /sys/devices/system/cpu/;ll
drwxr-xr-x 7 root root 0 Apr 15 15:29 cpu0
drwxr-xr-x 7 root root 0 Apr 15 15:29 cpu1
......
  • L1一級緩存查看:
# cat cpu0/cache/index0/level 
1
# cat cpu0/cache/index0/size
32K
# cat cpu0/cache/index0/type
Data
# cat cpu0/cache/index0/shared_cpu_list
0,12
# cat cpu0/cache/index1/level
1
# cat cpu0/cache/index1/size

32K
# cat cpu0/cache/index1/type
Instruction
# cat cpu0/cache/index1/shared_cpu_list
0,12

從上面的level接口可以看出index0和index1都是一級緩存,只不過一個是Data數據緩存,一個是Instruction也就是代碼緩存。

等等,上面提到的是每個Core是獨立的L1緩存,為什麼shared_cpu_list顯示有共享?對了我們這裡看到的cpu0並不是物理Core,而是邏輯核,都是超線程技術虛擬出來的。 實際上cpu0和cpu12是屬於一個物理Core,所以每個Data L1和Instruction是這兩個邏輯核共享的。

我的這臺電腦裡,總共是有12個Data L1,12個Instrunction L1,大小都是32K。

  • L2二級緩存查看:
# cat cpu0/cache/index2/size 
256K
# cat cpu0/cache/index2/type
Unified
# cat cpu0/cache/index2/shared_cpu_list
0,12

二級緩存要比一級緩存大不少,有256K,但是不分Data和Instruction。另外L2和L1一樣,也是總共有12個,每兩個邏輯核共享一個L2。

  • L3三級緩存查看:
# cat cpu0/cache/index3/size 
12288K
# cat cpu0/cache/index3/type
Unified
# cat cpu0/cache/index3/shared_cpu_list
0-5,12-17
#cat cpu6/cache/index3/shared_cpu_list
6-11,18-23

L3達到了12M,你去買CPU的時候商品裡能看到的緩存屬性一般告訴你的就是這個L3屬性。因為L3要比L2和L1看起來要大的多,能激發你購買的慾望。但實際上我的這臺電腦裡L3只有兩個,每個CPU各一個,不像是L2、L1有很多。第0-5,12-17號邏輯核共享一個L3,因為它們是在一個物理CPU上。6-11,18-23共享另一個。

另外,Linux上還有個dmidecode命令,也能查看到一些關於CPU緩存的信息,感興趣的小夥伴們可以試試

# dmidecode -t cache

可能有的同學會問了,我用的操作系統是windows啊,怎麼看?打開cmd命令行,輸入以下命令試試吧,飛哥在windows上知道的就這麼多了,感興趣的話你自己google上搜搜吧。

# wmic cpu get L2CacheSize,L3CacheSize

擴展知識

Cache Line:我們前面只介紹了各個級別的緩存,但是這裡面有個很重要的概念就是Cache Line,就是本級緩存向下一層取數據時的基本單位。可以通過如下方式查看:

# cd /sys/devices/system/cpu/;ll
# cat cpu0/cache/index0/coherency_line_size
64
# cat cpu0/cache/index1/coherency_line_size
64
# cat cpu0/cache/index2/coherency_line_size
64
# cat cpu0/cache/index3/coherency_line_size
64

可以看到L1、L2、L3的Cache Line大小都是64字節(注意是字節)。就是說每次cpu從內存獲取數據的時候,都是以該單位來進行的,哪怕你只取一個bit,CPU也是給你取一個Cache Line然後放到各級緩存裡存起來。請大家牢牢記住這個概念,以後的文章中我們會用到。


分享到:


相關文章: