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