NUMA架構下的內存訪問延遲區別!

圖片

如今的服務器物理機通常都是多個CPU,核數也是十幾甚至幾十核。內存幾十GB甚至是上百G,也是由許多條組成的。那麼我這裏思考一下,這麼多的CPU和內存它們之間是怎麼互相鏈接的?同一個CPU核訪問不一樣的內存條延時同樣嗎?
前端

《內存隨機訪問也比順序慢,帶你深刻理解內存IO過程》中咱們瞭解了內存訪問時芯片內部的執行過程,在《實際測試內存在順序IO和隨機IO時的訪問延時差別》中咱們又進行了實際的代碼測試。不過這兩文中咱們都把精力聚焦在內存內部機制,而回避了上面的問題,那就是CPU和內存的鏈接方式,也就是總線架構。node

1回顧CPU與內存的簡單鏈接:FSB時代linux

咱們先來回顧下在歷史上CPU、內存數量比較少的年代裏的總線方案-FSB。FSB的全稱是Front Side Bus,所以也叫前端總線。CPU經過FSB總線鏈接到北橋芯片,而後再鏈接到內存。內存控制器是集成在北橋裏的,Cpu和內存之間的通訊所有都要經過這一條FSB總線來進行。
數組

圖片圖1 FSB總線架構服務器

在這個年代裏,當時提升計算機系統總體性能的方式就是不斷地提升CPU、FSB總線、內存條的數據傳輸頻率。架構

2現在多CPU多內存複雜互聯:NUMA時代dom

當CPU的主頻提高到了3GHz每秒之後,硬件製造商們發現單個CPU的已經到了物理極限了。因此就改變了性能改進的方法,改爲爲向多核、甚至是多CPU的方向來發展。在這種狀況下,若是仍然採用FSB總線,會致使全部的CPU和內存通訊都通過總線,這樣總線就成爲了瓶頸,沒法充分發揮多核的優點與性能。因此CPU製造商們把內存控制器從北橋搬到了CPU內部,這樣CPU即可以直接和本身的內存進行通訊了。那麼,若是CPU想要訪問不和本身直連的內存條怎麼辦呢?因此就誕生了新的總線類型,它就叫QPI總線。
ide

圖片圖2 QPI總線架構性能

圖2中CPU1若是想要訪問內存3的話,就須要通過QPS總線才能夠。測試

3動手查看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裏的內存要比其它內存要快!

4動手測試NUMA架構內存延遲差別

numactl命令有--cpubind--membind的選項,經過它們咱們能夠指定咱們要用的node節點。還沿用《實際測試內存在順序IO和隨機IO時的訪問延時差別》裏的測試代碼

一、讓內存和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
random   2.40    2.40    2.40    2.40    4.80    4.80    19.20   28.80   52.80

二、讓內存和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
random   2.40    2.40    2.40    2.40    4.80    4.80    19.20   31.20   52.80

5結論

經過上面的各個小節咱們能夠看到,現代的服務器裏,CPU和內存條都有多個,它們以前目前主要採用的是複雜的NUMA架構進行互聯,NUMA把服務器裏的CPU和內存分組劃分紅了不一樣的node。從上述實驗結果來看,拿8M數組,循環步長爲64的case來講,同node耗時3.15納秒,跨node爲3.96納秒。因此屬於同一個node裏的CPU和內存之間訪問速度會比較快。而若是跨node的話,則須要通過QPI總線,整體來講,速度會略慢一些。

相關文章
相關標籤/搜索