天天看點

NUMA架構下的記憶體延遲差別測試!

現在的伺服器實體機CPU一般都是多個CPU,核數也是十幾甚至幾十核。記憶體幾十GB甚至是上百G,也是由許多的記憶體條組成的。那麼我這裡思考一下,這麼多的CPU和記憶體它們之間是怎麼互相連接配接的?同一個CPU核通路不同的記憶體條延時一樣嗎?

在《記憶體随機通路也比順序慢,帶你深入了解記憶體IO過程》中我們了解了記憶體通路時晶片内部的執行過程,在《實際測試記憶體在順序IO和随機IO時的通路延時差異》中我們又進行了實際的代碼測試。不過這兩文中我們都把精力聚焦在記憶體内部機制,而回避了上面的問題,那就是CPU和記憶體的連接配接方式,也就是總線架構。

回顧CPU與記憶體的簡單連接配接:FSB時代

我們先來回顧下在曆史上CPU、記憶體數量比較少的年代裡的總線方案-FSB。FSB的全稱是Front Side Bus,是以也叫前端總線。CPU通過FSB總線連接配接到北橋晶片,然後再連接配接到記憶體。記憶體控制器是內建在北橋裡的,Cpu和記憶體之間的通信全部都要通過這一條FSB總線來進行。

NUMA架構下的記憶體延遲差別測試!

在這個年代裡,當時提高計算機系統整體性能的方式就是不斷地提高CPU、FSB總線、記憶體條的資料傳輸頻率。

如今多CPU多記憶體條複雜互聯:NUMA時代

當CPU的主頻提升到了3GHz每秒以後,硬體制造商們發現單個CPU的已經到了實體極限了。是以就改變了性能改進的方法,改成為向多核、甚至是多CPU的方向來發展。在這種情況下,如果仍然采用FSB總線,會導緻所有的CPU和記憶體通信都經過總線,這樣總線就成為了瓶頸,無法充分發揮多核的優勢與性能。是以CPU制造商們把記憶體控制器從北橋搬到了CPU内部,這樣CPU便可以直接和自己的記憶體進行通信了。那麼,如果CPU想要通路不和自己直連的記憶體條怎麼辦呢?是以就誕生了新的總線類型,它就叫QPI總線。

NUMA架構下的記憶體延遲差別測試!

圖中CPU1如果想要通路記憶體3的話,就需要經過QPS總線才可以。

動手檢視Linux下NUMA架構

我們先通過dmidecode指令檢視一下記憶體插槽,單條大小等資訊。大家可以試着在linux上執行以下該指令。輸出結果很長,大家可以有空仔細研究。我這裡不全部介紹,這裡隻挑選一些和記憶體相關的:

# dmidecode|grep -P -A5 "Memory\s+Device"|grep Size  
        Size: 8192 MB  
        Size: 8192 MB  
        Size: No Module Installed  
        Size: 8192 MB  
        Size: No Module Installed  
        Size: 8192 MB  
        Size: 8192 MB  
        Size: 8192 MB  
        Size: No Module Installed  
        Size: 8192 MB  
        Size: No Module Installed  
        Size: 8192 MB  
           

可以看出,我目前使用的機器上共有16個記憶體插槽,共插了8條8G的記憶體。是以總共是64GB。如我們前面所述,在NUMA架構裡,每一個實體CPU都有不同的記憶體組,通過

numactl

指令可以檢視這個分組情況。

# numactl --hardware
available: 2 nodes (0-1)
node 0 cpus: 0 1 2 3 4 5 12 13 14 15 16 17
node 0 size: 32756 MB
node 0 free: 19642 MB
node 1 cpus: 6 7 8 9 10 11 18 19 20 21 22 23
node 1 size: 32768 MB
node 1 free: 18652 MB
node distances:
node   0   1
  0:  10  21
  1:  21  10
           

通過上述指令可以看到,每一組CPU核配置設定了32GB(4條)的記憶體。

node distance

是一個二維矩陣,描述node通路所有記憶體條的延時情況。

node 0

裡的CPU通路

node 0

裡的記憶體相對距離是

10

,因為這時通路的記憶體都是和該CPU直連的。而

node 0

如果想通路

node 1

節點下的記憶體的話,就需要走QPI總線了,這時該相對距離就變成了

21

是以、在NUMA架構下,CPU通路自己同一個node裡的記憶體要比其它記憶體要快!

動手測試NUMA架構記憶體延遲差異

numactl

指令有

--cpubind

--membind

的選項,通過它們我們可以指定我們要用的node節點。還沿用《用代碼讓你來實際感受記憶體的在不同情況下的通路延時差異》裡的測試代碼

1、讓記憶體和CPU處于同一個node

# numactl --cpubind=0 --membind=0 ./main
Delay  (ns)
        2k      8k      32k     128k    512k    2m      8m      32m     128m
s1      1.28    1.28    1.26    1.25    1.26    1.26    1.28    1.43    1.43
s32     1.27    1.26    1.32    1.78    2.67    2.73    3.27    9.95    10.37
s64     1.28    1.26    1.26    1.82    2.43    2.48    3.15    8.82    8.92
andom   2.40    2.40    2.40    2.40    4.80    4.80    19.20   28.80   52.80
           

2、讓記憶體和CPU處于不同node

# numactl --cpubind=0 --membind=1 ./main
Delay  (ns)
        2k      8k      32k     128k    512k    2m      8m      32m     128m
s1      1.29    1.28    1.26    1.26    1.26    1.26    1.31    1.62    1.63
s32     1.29    1.26    1.33    1.77    2.80    2.92    3.95    13.69   13.77
s64     1.30    1.27    1.26    1.82    2.47    2.48    3.96    12.93   12.90
andom   2.40    2.40    2.40    2.40    4.80    4.80    19.20   31.20   52.80
           

結論

通過上面的各個小節我們可以看到,現代的伺服器裡,CPU和記憶體條都有多個,它們之前目前主要采用的是複雜的NUMA架構進行互聯,NUMA把伺服器裡的CPU和記憶體分組劃分成了不同的node。從上述實驗結果來看,拿8M數組,循環步長為64的case來說,同node耗時3.15納秒,跨node為3.96納秒。是以屬于同一個node裡的CPU和記憶體之間通路速度會比較快。而如果跨node的話,則需要經過QPI總線,總體來說,速度會略慢一些。

開發内功修煉之記憶體篇專輯:

  • 1.帶你深入了解記憶體對齊最底層原理
  • 2.記憶體随機也比順序通路慢,帶你深入了解記憶體IO過程
  • 3.從DDR到DDR4,記憶體核心頻率其實基本上就沒太大的進步
  • 4.實際測試記憶體在順序IO和随機IO時的通路延時差異
  • 5.揭穿記憶體廠家“謊言”,實測記憶體帶寬真實表現
  • 6.NUMA架構下的記憶體通路延遲差別!
  • 7.PHP7記憶體性能優化的思想精髓
  • 8.一次記憶體性能提升的項目實踐
  • 9.挑戰Redis單執行個體記憶體最大極限,“遭遇”NUMA陷阱!

我的公衆号是「開發内功修煉」,在這裡我不是單純介紹技術理論,也不隻介紹實踐經驗。而是把理論與實踐結合起來,用實踐加深對理論的了解、用理論提高你的技術實踐能力。歡迎你來關注我的公衆号,也請分享給你的好友~~~