(1)
一个[合格的]Oracle DBA在安装数据库的时候,通常都会按要求关闭NUMA(MOS:Disable NUMA At OS Level (Doc ID 2193586.1)),因为启用NUMA会导致CPU彪高,性能很差(MOS:High CPU Usage when NUMA enabled (Doc ID 953733.1))。也许是这类问题太多,从Oracle 11gR2开始,默认就关闭了NUMA特性,因为NUMA的使用比较苛刻,要结合硬件、操作系统和Oracle版本(MOS:Oracle NUMA Usage Recommendation (Doc ID 759565.1))以及应用程序。稍有不对,努力白费,所以乖乖的关掉NUMA,是比较正确的事情。
同时还搞了个隐含参数来应对想用NUMA的人(还有几个类似的NUMA隐含参数,谨慎对待):
_enable_NUMA_support=TRUE
还特意加了强调:
Recommendation:
· Customers who have tuned their Database specifically for NUMA can continue to run with NUMA enabled with Oracle Server Version 11.2.0.1.
· It is strongly recommended to customers who want to enable NUMA do sufficient testing before going into production.
这也没辙,O记实在是被NUMA搞怕了(Doc ID 759565.1):
如何检验NUMA特性被禁用了:
# numactl -H
available: 1 nodes (0)
node 0 size: 4195 MB
node 0 free: 3304 MB
node distances:
node 0
0: 10
不然可能至少有2个node。
(2)
那NUMA到底是啥玩意呢?
要搞清楚其实不太容易,要花点时间。
从硬件的角度来看,NUMA(non-uniform memory access,非一致性内存访问)是一个计算机平台,它包含多个组件/集成片,每个组件/集成片包含多个CPU、本地内存和I/O总线。为简洁起见,并从软件抽象中消除对这些物理组件/集成片的硬件视图的歧义,后续给了这些组件/集成片一个统一的名字,称为socket。
每个socket都可以看作是SMP对称多处理器的子集——独立SMP系统所需的某些组件可能不会放到socket上。NUMA系统的socket通过某种系统互连连接在一起,例如,交叉或点对点链路是NUMA系统互连的常见类型。这两种类型的互连可以聚合在一起,以创建与其他socket具有多个距离的socket的NUMA平台(这句话有点绕,在启用NUMA的OS里,你用numactl -H命令看到输出的distances部分,就大概明白这句话的意思了)。
这是一个4-way的物理的服务器主板图。看到右侧4个黄色标签的东东了么,这就是一个socket了,离它最近的那4根内存条就是它的了。通常我们一般就还有一个socket,带4根内存条,那就是传统的SMP架构。
上2张逻辑抽象图片,可能更清晰一些。第一章图例有显示node0的CPU可能会去访问node2的memory,这就会造成某些业务的性能影响或者是抖动。
分别是2-way 8cores CPU的NUMA架构和4-way 24cores 的NUMA架构。所谓的非一致内存访问NUMA,就是指这里的local access和remote access了,它们的路径长短不一样,成不不一样,所以是非一致的。
需要注意的是,上面图中的node,事实上是Linux系统中的一个逻辑概念,跟硬件层面的socket对应,也可以混用。
对于Linux系统,感兴趣的是NUMA平台所谓的Cache Coherent NUMA或ccNUMA系统。在ccNUMA系统中,所有的内存对连接到任何socket的任何cpu都是可见的和可访问的,并且高速缓存的一致性由处理器高速缓存和系统互连在硬件中处理。
内存访问时间和有效内存带宽取决于包含CPU/IO总线的socket到包含目标memory的socket之间的距离。例如,通过连接到同一个socket的CPU访问内存将比访问其他远程socket上的内存更快,带宽更高。
NUMA硬件提供商并不构建NUMA系统。这种架构是一种提供可伸缩内存带宽的方法。然而,为了实现可伸缩的内存带宽,系统和应用软件必须将大部分内存使用安排为“本地”内存(即则为同一socket上的内存)或与内存最接近的socket。
因此,Linux系统将NUMA的硬件资源划分为多个称为node的软件抽象。Linux将node映射到硬件平台的物理socket上,为这个体系架构抽象出一些细节。跟物理socket一样,软件node可以包含0个或多个CPU、内存和I/O总线。访问“更近”node上的内存(即映射到更近的socket的node)通常比访问更远的socket会得到更快的访问时间和更高的有效带宽。
对于某些体系结构(如x86),Linux会“隐藏”表示附加内存的socket上的node,并将附加到该socket的任何CPU重新分配给表示具有内存的socet(node)。因此,在这些体系结构中,不能假定linux与给定node关联的所有cpu都将看到相同的本地内存访问时间和带宽。
另外,对于某些体系结构(如x86),linux支持模拟其他node。对于NUMA仿真,Linux将把现有的node(或者非NUMA平台的系统内存)分割成多个node。每个模拟node将管理底层socket的一小部分物理内存。NUMA emluation对于在非numa平台上测试NUMA内核和应用程序特性以及与cpusets一起使用时作为一种内存资源管理机制非常有用。
每个有内存的node,Linux构建了一个独立的内存管理子系统,包括自己的空闲页面列表、正在使用的页面列表、使用统计信息和锁,以斡旋(mediate)访问。此外,Linux为每个内存区域(dma、dma32、normal、high_memory、movable中的一个或多个)构造一个有序的“zonelist”。当选定的区域/node无法满足分配请求时,Zonelist会指定某个区域/node供访问。当区域没有可用内存来满足请求时,这种情况称为“overflow”或“fallback”。这个过程,其实就是一个斡旋的过程。
系统管理员和应用程序设计人员可以使用各种CPU关联命令行接口(如taskset和numactl)以及程序接口(如sched_setaffinity)限制任务的迁移,以改进NUMA局部性,让特定业务获得更好性能。还可以使用Linux NUMA内存策略修改内核的默认本地分配行为。
系统管理员可以使用控制组和CPUset 限制非特权用户在调度函数时使用指定的CPU和node内存。
(借用一张图)
在本图中,node0/node1的内存大小都是32GB,每个node上有10颗CPU。这里的CPU,如果你用cat /etc/interrupts看的话,会显示为Core.
在《NUMA Best Practices for Dell PowerEdge 12th Generation Servers》(P13,2012)一书中,有这么一张图,这里的一个socket上有2个node,它是AMD处理器。
(3)来看看
HPE Proliant系列的NUMA情况。
Linux Kernel从2.6开始支持ccNUMA系统,目前最新的已经是Kernel 5了,虽然RHEL 7.x还用的是3.10。
我们可以看到,因为采用了交叉互联架构,所以除了访问本地内存之外,其他node上的内存的距离是一样的。
但就算是距离一样,其实跨节点的内存访问的带宽并非是一样的,而且各个型号都不一样。DL580服务器( DL580 G7 with 2.40 GHz ten core Xeon E7 4870)各node间内存访问的带宽:
DL560、DL585的NUMA架构跟DL580又不太一样,各node间内存访问带宽又会有差别。这里的0.52/0.34,是指带宽相当于本地带宽的52%。DL580 Gen10比DL560会好一些,是0.47/0.44。
可以用语句numactl实测访问不同node的内存的带宽,下面是个示例:
# numactl --cpubind=0 --membind=0 dd if=/dev/zero of=/dev/shm/A bs=1M count=1024
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 0.823497 s, 1.3 GB/s
# numactl --cpubind=0 --membind=1 dd if=/dev/zero of=/dev/shm/A bs=1M count=1024
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 0.936182 s, 1.1 GB/s
虽然差距不是很大,还是要尽量避免跨节点访问内存。
那么怎么避免node0的内存溢出导致node外分配呢?
如前面在第(2)节所描述的,当策略选择的node无法满足请求时,除绑定模式(membind)外,所有Linux内存策略模式都允许分配溢出(overlow)或退回(fallback)到其他节点,通过SLIT(系统局部信息表)斡旋。
Linux 使用内核参数vm.zone_reclaim_mode来控制node溢出。
当vm.zone_reclaim_mode被禁用或为零时,内核将溢出到目标node区域列表中的下一个node。
启用vm.zone_reclaim_模式时,内核在离开目标node进行分配之前尝试从目标node的内存中释放或回收页面。相当于是多一次机会。
当所有异地node的距离都是20时,默认是disable的。启用还是不启用呢?通过应用实际测试后再定。
(4) HPE Proliant Gen10的设置
首先是BIOS中,“NUMA Group Size Optimization”,默认是“clustered”,但如果应用设计的时候没有考虑到使用跨多组处理器的使用,那么就建议选择“flat”。
Linux将每个NUMA node包含的内存视为一个单独的可用内存池。每个池都有自己的可用页列表、用于管理在用的LRU列表、统计信息和其他管理结构(包括序列化对列表的访问的锁)。内核将这些数据结构分配到由这些数据结构管理的node的内存中。Linux通过使本地CPU对node的内存请求有利于该node的页面池,从而最大化自己的内存访问和请求内存的任务的本地性。
随着新版本内核对Linux NUMA支持的改进,如Red Hat Enterprise Linux 5、6和7,节点交错(node interleaving)式不具优势,特别是在更大的系统配置上。在某些情况下,节点交错会导致显著的性能下降。当在系统firmware中启用节点交错时,内核不知道内存页相对于系统实际NUMA拓扑的位置。。结果,数据结构可以被分配到距离它们被大量使用的地方最远的页面上,从而导致次优的内核和应用程序性能。所以HPE不建议启用节点交错(node interleaving)。
怎么做?
当你进去BIOS之后,你还会看到一个option,Channel interleaving,要不要改呢?根据表Workload Profiles General Power Efficient Compute—Low Latency的列式,所有模式都应该是Enabled。千万不能改错了。
那什么是memory interleaving/channel interleaving呢?
好多文章被墙了,这里有一篇讲了high order/lower order,基本就是我们通常讲的little endian.:http://fourier.eng.hmc.edu/e85_old/lectures/memory/node2.html
一般来说,CPU更可能需要访问存储器以获得一组连续的字(程序中的连续指令段或数据结构的组件,例如数组), Lower Order arrangement的情况下memory interleaved会更优的,因为连续的字在不同的模块中可以同时提取。所以就不需要更改了。
文章内容可能有错,如果发现,欢迎指出。
参考内容:
1.https://www.kernel.org/doc/html/latest/vm/numa.html
2.Red Hat Linux NUMA Support for HP ProLiant Servers(https://support.hpe.com/hpsc/doc/public/display?docId=emr_na-c03261871)
3.Red Hat Enterprise Linux NUMA support for HPE ProLiant servers(https://h50146.www5.hpe.com/products/software/oe/linux/mainstream/support/whitepaper/pdfs/a00039147enw.pdf)
4.UEFI System Utilities User Guide for HPE ProLiant Gen10 Servers and HPE Synergy(https://support.hpe.com/hpsc/doc/public/display?docId=emr_na-a00016407ja_jp)
5.Linux NUMA support for HP ProLiant servers(https://h50146.www5.hpe.com/products/software/oe/linux/mainstream/support/whitepaper/pdfs/c03261871_2012.pdf)
6.https://blog.csdn.net/shaoyunzhe/article/details/53606584
7.UEFI System Utilities User Guide for HPE ProLiant Gen10 Servers and HPE Synergy(https://techlibrary.hpe.com/docs/iss/proliant_uefi/UEFI_Gen9_121417/s_enable_node_interleaving.html)