Linux工具之numactl

  NUMA(Non-Uniform Memory Access)字面直譯爲“非一致性內存訪問”,對於Linux內核來說最早出現在2.6.7版本上。這種特性對於當下大內存+多CPU爲潮流的X86平臺來說確實會有不少的性能提升,但相反的,如果配置不當的話,也是一個很大的坑。本文就從頭開始說說Linux下關於CPU NUMA特性的配置和調優。
  最早Intel在Nehalem架構上實現了NUMA,取代了在此之前一直使用的FSB前端總線的架構,用以對抗AMD的HyperTransport技術。一方面這個架構的特點是內存控制器從傳統的北橋中移到了CPU中,排除了商業戰略方向的考慮之外,這樣做的方法同樣是爲了實現NUMA。
  在SMP多CPU架構中,傳統上多CPU對於內存的訪問是總線方式。是總線就會存在資源爭用和一致性問題,而且如果不斷的增加CPU數量,總線的爭用會愈演愈烈,這就體現在4核CPU的跑分性能達不到2核CPU的2倍,甚至1.5倍!理論上來說這種方式實現12core以上的CPU已經沒有太大的意義。
  Intel的NUMA解決方案,Litrin始終認爲它來自本家的安藤。他的模型有點類似於MapReduce。放棄總線的訪問方式,將CPU劃分到多個Node中,每個node有自己獨立的內存空間。各個node之間通過高速互聯通訊,通訊通道被成爲QuickPath Interconnect即QPI。
  這個架構帶來的問題也很明顯,如果一個進程所需的內存超過了node的邊界,那就意味着需要通過QPI獲取另一node中的資源,儘管QPI的理論帶寬遠高於傳統的FSB,比如當下流行的內存數據庫,在這種情況下就很被動了。
  Linux提供了一個一個手工調優的命令numactl(默認不安裝),首先你可以通過它查看系統的numa狀態:

root@dc-skyeye:/usr/bin# numactl --hardware
available: 2 nodes (0-1)
node 0 cpus: 0 1 2 3 4 5 6 7 16 17 18 19 20 21 22 23
node 0 size: 131037 MB
node 0 free: 3019 MB
node 1 cpus: 8 9 10 11 12 13 14 15 24 25 26 27 28 29 30 31
node 1 size: 131071 MB
node 1 free: 9799 MB
node distances:
node 0 1
 0: 10 20
 1: 20 10

  此係統共有2個node,各領取16個CPU和128G內存。
  這裏假設我要執行一個java param命令,此命令需要120G內存,一個python param命令,需要16G內存。最好的優化方案時python在node0中執行,而java在node1中執行,那命令是:

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

  當然,也可以自找沒趣

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

  對於一口氣吃掉內存大半的MongoDB,我的配置是:

# numactl --interleave=all mongod -f /etc/mongod.conf

  即分配所有的node供其使用,這也是官方推薦的用法。
  通過numastat命令可以查看numa狀態

# numastat
 node0 node1
numa_hit 1775216830 6808979012
numa_miss 4091495 494235148
numa_foreign 494235148 4091495
interleave_hit 52909 53004
local_node 1775205816 6808927908
other_node 4102509 494286252

  other_node過高意味着需要重新規劃numa.

NUNA與SMP

  NUMA(Non-Uniform Memory Access,非一致性內存訪問)和SMP(Symmetric Multi-Processor,對稱多處理器系統)是兩種不同的CPU硬件體系架構。
  SMP的主要特徵是共享,所有的CPU共享使用全部資源,例如內存、總線和I/O,多個CPU對稱工作,彼此之間沒有主次之分,平等地訪問共享的資源,這樣勢必引入資源的競爭問題,從而導致它的擴展內力非常有限。
  NUMA技術將CPU劃分成不同的組(Node),每個Node由多個CPU組成,並且有獨立的本地內存、I/O等資源。Node之間通過互聯模塊連接和溝通,因此除了本地內存外,每個CPU仍可以訪問遠端Node的內存,只不過效率會比訪問本地內存差一些,我們用Node之間的距離(Distance,抽象的概念)來定義各個Node之間互訪資源的開銷。

Node->Socket->Core->Processor

隨着多核技術的發展,將多個CPU封裝在一起,這個封裝被稱爲插槽Socket;Core是socket上獨立的硬件單元;通過intel的超線程HT技術進一步提升CPU的處理能力,OS看到的邏輯上的核數Processor。

socket = node

socket是物理概念,指的是主板上CPU插槽;node是邏輯概念,對應於socket。

core = 物理CPU

core是物理概念,一個獨立的硬件執行單元,對應於物理CPU;

thread = 邏輯CPU = Processor

thread是邏輯CPU,也就是Processor。

Reference:
http://www.litrin.net/2017/10/31/%E6%B7%B1%E6%8C%96numa/
http://www.litrin.net/2017/08/03/numa%E5%AF%B9%E6%80%A7%E8%83%BD%E7%9A%84%E5%BD%B1%E5%93%8D/
https://blog.csdn.net/ustc_dylan/article/details/45667227
http://kodango.com/cpu-topology
https://blog.csdn.net/envy13/article/details/80241886





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章