Linux numactl命令與多核調優

一、基礎概念

SMP(Symmetric Multi-Processor)
在這裏插入圖片描述
所謂對稱多處理器結構,是指服務器中多個CPU對稱工作,無主次或從屬關係。各CPU共享相同的物理內存,每個 CPU訪問內存中的任何地址所需時間是相同的,因此SMP也被稱爲一致存儲器訪問結構(UMA:Uniform Memory Access)。對SMP服務器進行擴展的方式包括增加內存、使用更快的CPU、增加CPU、擴充I/O(槽口數與總線數)以及添加更多的外部設備(通常是磁盤存儲)。
SMP服務器的主要特徵是共享,系統中所有資源(CPU、內存、I/O等)都是共享的。也正是由於這種特徵,導致了SMP服務器的主要問題,那就是它的擴展能力非常有限。對於SMP服務器而言,每一個共享的環節都可能造成SMP服務器擴展時的瓶頸,而最受限制的則是內存。由於每個CPU必須通過相同的內存總線訪問相同的內存資源,因此隨着CPU數量的增加,內存訪問衝突將迅速增加,最終會造成CPU資源的浪費,使 CPU性能的有效性大大降低。

有實驗數據表明,SMP型的服務器CPU最好是2-4顆就OK了,多餘的就浪費了。
在這裏插入圖片描述
NUMA(Non-Uniform Memory Access)
在這裏插入圖片描述
由於SMP在擴展能力上的限制,人們開始探究如何進行有效地擴展從而構建大型系統的技術,NUMA就是這種努力下的結果之一。利用NUMA技術,可以把幾十個CPU(甚至上百個CPU)組合在一個服務器內。NUMA服務器的基本特徵是具有多個CPU模塊,每個CPU模塊由多個CPU(如4個)組成,並且具有獨立的本地內存、I/O槽口等。由於其節點之間可以通過互聯模塊(如稱爲Crossbar Switch)進行連接和信息交互,因此每個CPU可以訪問整個系統的內存(這是NUMA系統與MPP系統的重要差別)。顯然,訪問本地內存的速度將遠遠高於訪問遠地內存(系統內其它節點的內存)的速度,這也是非一致存儲訪問NUMA的由來。由於這個特點,爲了更好地發揮系統性能,開發應用程序時需要儘量減少不同CPU模塊之間的信息交互。利用NUMA技術,可以較好地解決原來SMP系統的擴展問題,在一個物理服務器內可以支持上百個CPU。比較典型的NUMA服務器的例子包括HP的Superdome、SUN15K、IBMp690等。
每個CPU模塊之間都是通過互聯模塊進行連接和信息交互,CPU都是互通互聯的,同時,每個CPU模塊平均劃分爲若干個Chip(不多於4個),每個Chip都有自己的內存控制器及內存插槽。

  • 在NUMA中還有三個節點的概念:
  1. 本地節點:對於某個節點中的所有CPU,此節點稱爲本地節點。
  2. 鄰居節點:與本地節點相鄰的節點稱爲鄰居節點。
  3. 遠端節點:非本地節點或鄰居節點的節點,稱爲遠端節點。
  4. 鄰居節點和遠端節點,都稱作非本地節點(Off Node)。

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

二、numactl相關命令

  1. 安裝
#yum install numactl -y
  1. 驗證系統是否支持numa
dmesg | grep -i numa查看輸出結果:
如果輸出結果爲:
No NUMA configuration found
說明numa爲disable,如果不是上面的內容說明numa爲enable
  1. 查看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
1234567
  1. 列舉系統上的NUMA節點
#numactl --hardware  
  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
12345678

說明:

  • numa_hit—命中的,也就是爲這個節點成功分配本地內存訪問的內存大小
  • numa_miss—把內存訪問分配到另一個node節點的內存大小,這個值和另一個node的numa_foreign相對應。
  • numa_foreign–另一個Node訪問我的內存大小,與對方node的numa_miss相對應
  • local_node----這個節點的進程成功在這個節點上分配內存訪問的大小
  • other_node----這個節點的進程 在其它節點上分配的內存訪問大小
    很明顯,miss值和foreign值越高,就要考慮綁定的問題。
  1. 關閉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"
2、重新生成 /etc/grub2.cfg 配置文件:
# grub2-mkconfig -o /etc/grub2.cfg

三、調優

  1. NUMA的內存分配策略
1. 缺省(default):總是在本地節點分配(分配在當前進程運行的節點上);
2. 綁定(bind):強制分配到指定節點上;
3. 交叉(interleave):在所有節點或者指定的節點上交織分配;
4. 優先(preferred):在指定節點上分配,失敗則在其他節點上分配。
因爲NUMA默認的內存分配策略是優先在進程所在CPU的本地內存中分配,會導致CPU節點之間內存分配不均衡,當某個CPU節點的內存不足時,會導致swap產生,而不是從遠程節點分配內存。這就是所謂的swap insanity 現象。
在實際使用中,可能存在存在不同進程對內存消耗不同,可以考慮按照需求綁定到不同的核上
  1. 查看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
123456789101112

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
  1. 內核參數overcommit_memory
它是 內存分配策略,可選值:0、1、2。

- 0:表示內核將檢查是否有足夠的可用內存供應用進程使用;如果有足夠的可用內存,內存申請允許;否則,內存申請失敗,並把錯誤返回給應用進程。
- 1:表示內核允許分配所有的物理內存,而不管當前的內存狀態如何。
- 2:表示內核允許分配超過所有物理內存和交換空間總和的內存
  1. 內核參數zone_reclaim_mode:
可選值0、1
當某個節點可用內存不足時:
1、如果爲0的話,那麼系統會傾向於從其他節點分配內存
2、如果爲1的話,那麼系統會傾向於從本地節點回收Cache內存多數時候,Cache對性能很重要,所以0是一個更好的選擇
  1. mongodb的NUMA問題
mongodb日誌顯示如下:
WARNING: You are running on a NUMA machine.
We suggest launching mongod like this to avoid performance problems:
numactl –interleave=all mongod [other options]

解決方案,臨時修改numa內存分配策略爲 interleave=all (在所有node節點進行交織分配的策略):

1.在原啓動命令前面加numactl –interleave=all
如# numactl --interleave=all ${MONGODB_HOME}/bin/mongod --config conf/mongodb.conf
2.修改內核參數
echo 0 > /proc/sys/vm/zone_reclaim_mode ; echo "vm.zone_reclaim_mode = 0" >> /etc/sysctl.conf
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章