NUMA相关配置介绍

1 篇文章 0 订阅

NUMA相关配置介绍

什么是NUMA

在早期,对于x86架构的计算机,那时的内存控制器还没有整合进CPU,所有内存的访问都需要通过北桥芯片来完成。此时的内存访问如下图所示,被称为UMA(uniform memory access, 一致性内存访问 )。这样的访问对于软件层面来说非常容易实现:总线模型保证了所有的内存访问是一致的,不必考虑由不同内存地址之前的差异。

之后的x86平台经历了一场从“拼频率”到“拼核心数”的转变,越来越多的核心被尽可能地塞进了同一块芯片上,各个核心对于内存带宽的争抢访问成为了瓶颈;此时软件、OS方面对于SMP多核心CPU的支持也愈发成熟;再加上各种商业上的考量,x86平台也顺水推舟的搞了NUMA(Non-uniform memory access, 非一致性内存访问)。在这种架构之下,每个Socket都会有一个独立的内存控制器IMC(integrated memory controllers, 集成内存控制器),分属于不同的socket之内的IMC之间通过QPI link通讯。

然后就是进一步的架构演进,由于每个socket上都会有多个core进行内存访问,这就会在每个core的内部出现一个类似最早SMP架构相似的内存访问总线,这个总线被称为IMC bus。

于是,很明显的,在这种架构之下,两个socket各自管理1/2的内存插槽,如果要访问不属于本socket的内存则必须通过QPI link。也就是说内存的访问出现了本地/远程(local/remote)的概念,内存的延时是会有显著的区别的。这也是为什么在NUMA架构下有些应用性能反而更差的原因。

回到当前世面上的CPU,工程上的实现其实更加复杂了。以来看,两个Socket之之间通过各自的一条9.6GT/s的QPI link互访。而每个Socket事实上有2个内存控制器。双通道的缘故,每个控制器又有两个内存通道(channel),每个通道最多支持3根内存条(DIMM)。理论上最大单socket支持76.8GB/s的内存带宽,而两个QPI link,每个QPI link有9.6GT/s的速率(~57.6GB/s)事实上QPI link已经出现瓶颈了。

内核的NUMA的默认行为

Linux内核中/ , //文件定义了NUMA的数据结构和操作方式。在一个启用了NUMA支持的Linux中,Kernel不会将任务内存从一个NUMA node搬迁到另一个NUMA node。

一个进程一旦被启用,它所在的NUMA node就不会被迁移,为了尽可能的优化性能,在正常的调度之中,CPU的core也会尽可能的使用可以local访问的本地core,在进程的整个生命周期之中,NUMA node保持不变。

一旦当某个NUMA node的负载超出了另一个node一个阈值(默认25%),则认为需要在此node上减少负载,不同的NUMA结构和不同的负载状况,系统见给予一个延时任务的迁移——类似于漏杯算法。在这种情况下将会产生内存的remote访问。

NUMA node之间有不同的拓扑结构,各个 node 之间的访问会有一个距离(node distances)的概念,如numactl -H命令的结果有这样的描述:node distances:
node 0 1 2 3
0: 10 11 21 21
1: 11 10 21 21
2: 21 21 10 11
3: 21 21 11 10

可以看出:0 node 到0 node之间距离为10,这肯定的最近的距离,不提。0-1之间的距离远小于2或3的距离。这种距离方便系统在较复杂的情况下选择最合适的NUMA设定。
NUMA相关配置
查看 NUMA node 信息

点击(此处)折叠或打开

numactl --hardware

    # NUMA 关闭时:
    # available: 1 nodes (0) # node 列表
    # node 0 cpus: 0 1 .. # node0 核列表
    # node 0 size: 65523 MB # node0 总内存大小
    # node 0 free: 51796 MB # node0 空闲内存大小
    # node distances: # node 之间 distances 大小
    # node 0 # distances 会由矩阵来表示
    # 0: 10

查看 NUMA 绑定信息

点击(此处)折叠或打开

numactl --show

    # NUMA 关闭时:
    # policy: default
    # preferred node: current
    # physcpubind: 0 1 ... # 核绑定
    # cpubind: 0 # CPU 绑定
    # nodebind: 0 # node 绑定
    # membind: 0 # 内存绑定

查看 NUMA 统计信息

点击(此处)折叠或打开

numastat 等同于 cat /sys/devices/system/node/node[0…n]/numastat。
numastat
# NUMA 关闭时:
# node0
# numa_hit 5571187 //打算在本节点上分配内存,最后从本节点分配的次数
# numa_miss 0 //打算在本节点分配内存,最后却从其他节点分配的次数
# numa_foreign 0 //打算在其他节点分配内存,最后却从这个节点分配的次数
# interleave_hit 53465 //采用interleave策略最后从本节点分配的次数
# local_node 5571187//本节点上的进程,在本节点上分配的次数
# other_node 0 //其他节点进程,在本节点上分配的次数

NUMA 的 内存 分配策略

选项:

–localalloc, -l

规定进程从当前 node 上请求分配内存。

–membind=nodes, -m nodes

规定进程只能从指定的 nodes 上请求分配内存。

–preferred=node

指定了 一个 推荐的 node 来获取内存,如果失败,则尝试别的 node。

–interleave=nodes, -i nodes

规定进程从指定的 nodes 上,以 round robin 算法 交织地 请求分配内存。
NUMA的分配策略例子

点击(此处)折叠或打开

# Unset default cpuset awareness.
numactl --all

# Run ${process} on node 0 with memory allocated on node 0 and 1.
numactl --cpunodebind=0 --membind=0,1 ${process} ${process_arguments}

# Run ${process} on cpus 0-4 and 8-12 of the current cpuset.
numactl --physcpubind=+0-4,8-12 ${process} ${process_arguments}

# Run ${process} with its memory interleaved on all CPUs
numactl --interleave=all ${process} ${process_arguments}

# Run process as above, but with an option (-l) that would be confused with a numactl option.
numactl --cpunodebind=0 --membind=0,1 -- ${process} -l

# Run ${network-server} on the node of network device eth0 with its memory also in the same node.
numactl --cpunodebind=netdev:eth0 --membind=netdev:eth0 ${network-server}

# Set preferred node 1 and show the resulting state.
numactl --preferred=1 numactl --show

# Interleave all of the sysv shared memory region specified by /tmp/shmkey over all nodes.
numactl --interleave=all --shm /tmp/shmkey

# Place a tmpfs file on 2 nodes.
numactl --membind=2 dd if=/dev/zero of=/dev/shm/A bs=1M count=1024

numactl --membind=3 dd if=/dev/zero of=/dev/shm/A seek=1024 bs=1M count=1024

# Reset the policy for the shared memory file file to the default localalloc policy.
numactl --localalloc /dev/shm/file

查看设备NUMA

事实上,在PCIe channel上也是有NUMA亲和性的。比如:查看网卡enp0s20f0u5的NUMA,用到了netdev:<设备名称>这种方式。

点击(此处)折叠或打开

[root@local ~]# numactl --prefer netdev:enp0s20f0u5 --show
policy: preferred
preferred node: 0
physcpubind: 0
cpubind: 0
nodebind: 0
membind: 0 1 2 3

或者一个PCI address 为00:17的SATA控制器,用到了pci:

点击(此处)折叠或打开

[root@local~]# numactl --prefer pci:00:17 --show
policy: preferred
preferred node: 0
physcpubind: 0
cpubind: 0
nodebind: 0
membind: 0 1 2 3

还有block/ip/file的方式查看NUMA affinity,这里也就不再累述了。

NUMA的开启和关闭

NUMA可以在BIOS和OS两个层面开关,其实关于两个层面开关的区别网上并没有找到详细资料。有一种说法是:BIOS和OS的关闭NUMA在interleave的粒度上有区别,BIOS应该是在cache line(64B)的粒度,而OS利用内核页表所以是页(4kB)的粒度。效果上BIOS表现应该更稳定一些,但OS的配置相对更方便。
BIOS 层 的 NUMA 设置

  1. 查看 BIOS 层是否开启 NUMA

    grep -i numa /var/log/dmesg

    #1. 如果为 “No NUMA configuration found”

    #则说明 NUMA 为 disable。

    #2. 如果不是 “No NUMA configuration found”

    #则说明 NUMA 为 enable。

  2. 修改 BIOS interleave

注意,由于 BIOS 种类繁多,请以实际情况为准。

参数路径:

BIOS: interleave

设定值:

Disable                # interleave 关闭,开启 NUMA。

Enable                # interleave 开启,关闭 NUMA。

OS 层 的 NUMA 设置

  1. 查询 当前内核启动参数

    cat /porc/cmdline

  2. 修改 内核启动参数

    vim /etc/grub.conf

    修改 kernel 或 linuxe 或 linuxefi 行

    #添加 numa=off,关闭 NUMA。

    #去除 numa=off,开启 NUMA。

    例子:

    linuxefi /vmlinuz-3.10.0-123.el7.x86_64 … numa=off

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值