目前的物理服务器CPU一般都有多个CPU,核心数都是十几甚至几十个核心。几十G甚至上百G的内存也是由很多内存条组成的。那么我在这里想一想,那么多的CPU和内存之间是怎么连接起来的呢?同一个CPU核心访问不同内存条的延迟是一样的吗?在《内存随机访问也比顺序慢,带你深入理解内存IO过程》中,我们了解了内存访问时芯片内部的执行流程,在《实际测试内存在顺序IO和随机IO时的访问延时差异》中,我们进行了实际的代码测试。不过,这两篇文章,我们着重讨论了内存的内部机制,而避免了上面的问题,即CPU与内存的连接方式,也就是总线架构。回顾一下CPU和内存的简单连接:外频时代我们先来回顾一下历史上CPU和内存数量比较少的时代的总线方案——外频。FSB的全称是FrontSideBus,所以又叫FrontSideBus。CPU通过FSB总线连接到北桥芯片,再连接到内存。内存控制器集成在北桥中,CPU与内存之间的所有通信都必须通过这条FSB总线进行。在这个时代,提高计算机系统整体性能的方法就是不断提高CPU、FSB总线和记忆棒的数据传输频率。如今,多个CPU、多个内存条复杂互联:在NUMA时代,当CPU的主频提升到每秒3GHz时,硬件厂商发现已经达到了单个CPU的物理极限。于是改变了性能提升的方法,改向多核甚至多CPU的方向发展。在这种情况下,如果仍然使用FSB总线,所有CPU和内存的通信都会通过总线,那么总线就会成为瓶颈,无法充分发挥多核的优势和性能。因此,CPU厂商将内存控制器从北桥移到了CPU内部,让CPU可以直接与自己的内存进行通信。那么,如果CPU要访问一个与自己没有直连的内存条怎么办?于是一种新的总线类型诞生了,它叫做QPI总线。图中,CPU1要访问内存3,需要经过QPS总线。手查Linux下的NUMA架构。下面通过dmidecode命令查看内存插槽、单条尺寸等信息。你可以尝试在linux上执行以下命令。输出很长,有时间可以仔细研究一下。这里就不一一介绍了,这里有一些内存相关的:#dmidecode|grep-P-A5"Memory\s+Device"|grepSizeSize:8192MBSize:8192MBSize:NoModuleInstalledSize:8192MB大小:未安装模块大小:8192MB大小:8192MB大小:8192MB大小:未安装模块大小:8192MB大小:未安装模块大小:8192MB可以看到内存条上有16个内存插槽我目前使用的机器一共插了八个8G内存插槽。所以一共64GB。前面我们提到,在NUMA架构中,每个物理CPU都有不同的内存组,可以通过numactl命令查看分组情况。#numactl--hardwareavailable:2nodes(0-1)node0cpus:012345121314151617node0size:32756MBnode0free:19642MBnode1cpus:67891011181920212223node1size:32768MBnode1free:18652MBnodedistances:node010:10211:2110通过上面的命令可以看到每组CPU核分配了32GB(4)的内存。节点距离是一个二维矩阵,描述节点访问所有记忆棒的延迟。0号节点的CPU和0号节点的内存的相对距离为10,因为此时访问的内存是直连CPU的。如果节点0要访问节点1下的内存,需要使用QPI总线。这时,相对距离就变成了21。所以在NUMA架构下,CPU访问同节点内存的速度比其他内存要快!动手测试NUMA架构内存延迟差异numactl命令有--cpubind和--membind选项,通过它们我们可以指定我们要使用的node节点。同样使用《用代码让你来实际感受内存的在不同情况下的访问延时差异》中的测试代码1,让内存和CPU在同一个节点#numactl--cpubind=0--membind=0./mainDelay(ns)2k8k32k128k512k2m8m32m128ms11.281.281.261.251.261.261.281.431.43s321.271.261.321.782.672.733.279.9510.37s641.281.261.261.822.432.483.158.828.92andom2.402.402.402.404.804.8019.2028.8052.802、让内存和CPU处于不同node#numactl--cpubind=0--membind=1./mainDelay(ns)2k8k32k128k512k2m8m32m128ms11.291.281.261.261.261.261.311.621.63s321.291.261.331.772.802.923.9513.6913.77s641.301.271.261.822.472.483.9612.9312.90andom2.402.402.402.404.804.8019.2031.2052.80结语通过以上几节我们可以看出,在现代服务器中,存在多个CPU和内存条。复杂的NUMA架构用于互连。NUMA将服务器中的CPU和内存划分到不同的节点中。从上面的实验结果来看,以8M数组,循环步长64为例,同一个节点耗时。3.15纳秒,跨节点3.96纳秒。因此,属于同一节点的CPU和内存之间的访问速度会更快。而如果跨节点,则需要经过QPI总线。一般来说,速度会稍微慢一些。练内功:内存部分:1.带你了解内存对齐的底层原理2.内存随机访问比顺序访问慢,让你深刻理解内存IO流程3.从DDR到DDR4,内存核心频率基本一致没太大进步4.实测内存有顺序IO和随机IO的访问延迟差异5.揭穿内存厂商的“谎言”,实测内存带宽的实际表现6.NUMA架构下内存访问延迟的区别!7.PHP7内存性能优化精髓8.一个内存性能提升的项目实践9.挑战Redis单实例内存最大极限,“遭遇”NUMA陷阱!我的公众号是《练内功》。在这里我不是简单地介绍技术理论,也不是只是介绍实践经验。而是理论联系实际,用实践加深对理论的理解,用理论提高技术实践能力。欢迎关注我的公众号,分享给你的朋友吧~~~
