NUMA-基礎篇


什么是NUMA?

NUMA中,雖然內存直接attach在CPU上,但是由於內存被平均分配在了各個die上。只有當CPU訪問自身直接attach內存對應的物理地址時,才會有較短的響應時間(后稱Local Access)。而如果需要訪問其他CPU attach的內存的數據時,就需要通過inter-connect通道訪問,響應時間就相比之前變慢了(后稱Remote Access)。

所以NUMA(Non-Uniform Memory Access)就此得名:非一致訪問分布共享存儲技術

 

每個CPU模塊之間都是通過互聯模塊進行連接和信息交互,CPU都是互通互聯的,同時,每個CPU模塊平均划分為若干個Chip(不多於4個),每個Chip都有自己的內存控制器及內存插槽。

在NUMA中還有三個節點的概念:

1)、本地節點:對於某個節點中的所有CPU,此節點稱為本地節點。

2)、鄰居節點:與本地節點相鄰的節點稱為鄰居節點。

3)、遠端節點:非本地節點或鄰居節點的節點,稱為遠端節點。

4)、鄰居節點和遠端節點,都稱作非本地節點(Off Node)。

CPU訪問不同類型節點內存的速度是不相同的,訪問本地節點的速度最快,訪問遠端節點的速度最慢,即訪問速度與節點的距離有關,距離越遠訪問速度越慢,此距離稱作Node Distance。應用程序要盡量的減少不通CPU模塊之間的交互,如果應用程序能有方法固定在一個CPU模塊里,那么應用的性能將會有很大的提升。

 

二、NUMA實踐

1、安裝numactl工具

Linux提供了一個手工調優的命令numactl(默認不安裝)

#yum install numactl -y

#numactl --hardware 列舉系統上的NUMA節點

 

2、查看numa狀態

# numactl --show 
policy: default
preferred node: current
physcpubind: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 
cpubind: 0 1 
nodebind: 0 1 
membind: 0 1

 

# numastat
node0 node1
numa_hit 1296554257 918018444
numa_miss 8541758 40297198
numa_foreign 40288595 8550361
interleave_hit 45651 45918
local_node 1231897031 835344122
other_node 64657226 82674322

說明:

  • numa_hit   —命中的,也就是為這個節點成功分配本地內存訪問的內存大小
  • numa_miss —把內存訪問分配到另一個node節點的內存大小,這個值和另一個node的numa_foreign相對應。
  • numa_foreign –另一個Node訪問我的內存大小,與對方node的numa_miss相對應
  • local_node ----這個節點的進程成功在這個節點上分配內存訪問的大小
  • other_node ----這個節點的進程 在其它節點上分配的內存訪問大小

很明顯,miss值和foreign值越高,就要考慮綁定的問題。

 

3、numad服務

在redhat6中,有一個numad的服務(需手工安裝),它可以自動的監控我們cpu狀況,並自動平衡資源,這個服務需要在內存使用量非常大的時候才會有明顯的效果,當內存空余量較大時,需要關閉KSM,避免發生沖突。官方說在某些內存使用巨大的環境中,可能會提高50%的性能。

# service numad start

 

4、查看cpu和內存使用情況

# numactl --hardware
available: 2 nodes (0-1)
node 0 cpus: 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30
node 0 size: 64337 MB
node 0 free: 1263 MB
node 1 cpus: 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31
node 1 size: 64509 MB
node 1 free: 30530 MB
node distances:
node 0 1 
0: 10 21 
1: 21 10

cpu0 可用 內存 1263 MB

cpu1 可用內存 30530 MB

當cpu0上申請內存超過1263M時必定使用swap,這個是很不合理的。

 

舉例:

這里假設我要執行一個java param命令,此命令需要1G內存;一個python param命令,需要8G內存。
最好的優化方案時python在node1中執行,而java在node0中執行,那命令是:

#numactl --cpubind=0 --membind=0 python param
#numactl --cpubind=1 --membind=1 java param


5、NUMA的內存分配策略

1.缺省(default):總是在本地節點分配(分配在當前進程運行的節點上);

2.綁定(bind):強制分配到指定節點上;

3.交叉(interleave):在所有節點或者指定的節點上交織分配;

4.優先(preferred):在指定節點上分配,失敗則在其他節點上分配。

因為NUMA默認的內存分配策略是優先在進程所在CPU的本地內存中分配,會導致CPU節點之間內存分配不均衡,當某個CPU節點的內存不足時,會導致swap產生,而不是從遠程節點分配內存。這就是所謂的swap insanity 現象。

舉例:

# numactl --hardware
node 0 cpus: 0 2 4 6
node 0 size: 65490 MB
node 0 free: 24447 MB
node 1 cpus: 1 3 5 7
node 1 size: 65536 MB
node 1 free: 16050 MB
node distances:
node 0 1 
0: 10 20 
1: 20 10

可以看到numa節點是2個,cpu物理節點是8個
現在我們綁定資源,兩顆cpu,每顆4個物理節點,那么我們開4個mysql實例,每個實例綁定2個cpu物理節點

numactl --physcpubind=0,3 --localalloc mysqld_multi --defaults-extra-file=/etc/mysqld_multi.cnf start 1

–physcpubind 指定綁定的cpu節點,

–localalloc表示使用內存方式,不交叉,以免降低性能,

mysqld_multi是mysql實例啟動命令

 

三、如何關閉NUMA

方法一:通過bios關閉

BIOS:interleave = Disable / Enable

 

方法二:通過OS關閉

1、編輯 /etc/default/grub 文件,加上:numa=off

GRUB_CMDLINE_LINUX="crashkernel=auto numa=off rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet"

注:參數只需加 numa=off 即可 (rd.lvm.lv是因為機器上做了lvm所以帶有對應參數)


2、重新生成 /etc/grub2.cfg 配置文件:

# grub2-mkconfig -o /etc/grub2.cfg

3、重啟操作系統

# reboot

4、確認:

# dmesg | grep -i numa
[ 0.000000] Command line: BOOT_IMAGE=/vmlinuz-3.10.0-327.el7.x86_64 root=/dev/mapper/centos-root ro crashkernel=auto numa=off rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet[ 0.000000] NUMA turned off[ 0.000000] Kernel command line: BOOT_IMAGE=/vmlinuz-3.10.0-327.el7.x86_64 root=/dev/mapper/centos-root ro crashkernel=auto numa=off rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet
# cat /proc/cmdline
BOOT_IMAGE=/vmlinuz-3.10.0-327.el7.x86_64 root=/dev/mapper/centos-root ro crashkernel=auto numa=off rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM