• 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
  • 相关阅读:
    OpenCL多次循环执行内核的一个简单样例
    Visual Studio2013的C语言编译器对C99标准的支持情况
    关于OpenCL中三重循环的执行次序
    jQuery判断复选框是否勾选
    JS动态增加删除UL节点LI
    Javascript玩转继承(三)
    Javascript玩转继承(二)
    Javascript玩转继承(一)
    js方法call和apply实例解析
    简单实用的php分页函数代码
  • 原文地址:https://www.cnblogs.com/leading-net/p/13082663.html
Copyright © 2020-2023  润新知