如今的服务器物理机通常都是多个CPU,核数也是十几甚至几十核。内存几十GB甚至是上百G,也是由许多条组成的。那么我这里思考一下,这么多的CPU和内存它们之间是怎么互相链接的?同一个CPU核访问不一样的内存条延时同样吗?
前端
在《内存随机访问也比顺序慢,带你深刻理解内存IO过程》中咱们了解了内存访问时芯片内部的执行过程,在《实际测试内存在顺序IO和随机IO时的访问延时差别》中咱们又进行了实际的代码测试。不过这两文中咱们都把精力聚焦在内存内部机制,而回避了上面的问题,那就是CPU和内存的链接方式,也就是总线架构。node
1回顾CPU与内存的简单链接:FSB时代linux
咱们先来回顾下在历史上CPU、内存数量比较少的年代里的总线方案-FSB。FSB的全称是Front Side Bus,所以也叫前端总线。CPU经过FSB总线链接到北桥芯片,而后再链接到内存。内存控制器是集成在北桥里的,Cpu和内存之间的通讯所有都要经过这一条FSB总线来进行。
数组
图1 FSB总线架构服务器
在这个年代里,当时提升计算机系统总体性能的方式就是不断地提升CPU、FSB总线、内存条的数据传输频率。架构
2现在多CPU多内存复杂互联:NUMA时代dom
当CPU的主频提高到了3GHz每秒之后,硬件制造商们发现单个CPU的已经到了物理极限了。因此就改变了性能改进的方法,改为为向多核、甚至是多CPU的方向来发展。在这种状况下,若是仍然采用FSB总线,会致使全部的CPU和内存通讯都通过总线,这样总线就成为了瓶颈,没法充分发挥多核的优点与性能。因此CPU制造商们把内存控制器从北桥搬到了CPU内部,这样CPU即可以直接和本身的内存进行通讯了。那么,若是CPU想要访问不和本身直连的内存条怎么办呢?因此就诞生了新的总线类型,它就叫QPI总线。
ide
图2 QPI总线架构性能
图2中CPU1若是想要访问内存3的话,就须要通过QPS总线才能够。测试
3动手查看Linux下的NUMA架构
咱们先经过dmidecode命令查看一下内存插槽,单条大小等信息。你们能够试着在linux上执行如下该命令。输出结果很长,你们能够有空仔细研究。我这里不所有介绍,这里只挑选一些和内存相关的:
# dmidecode|grep -P -A5 "Memory\s+Device"|grep Size
Size: 8192 MB
Size: 8192 MB
Size: No Module Installed
Size: 8192 MB
Size: No Module Installed
Size: 8192 MB
Size: 8192 MB
Size: 8192 MB
Size: No Module Installed
Size: 8192 MB
Size: No Module Installed
Size: 8192 MB
能够看出,我当前使用的机器上共有16个内存插槽,共插了8条8G的内存。因此总共是64GB。如咱们前面所述,在NUMA架构里,每个物理CPU都有不一样的内存组,经过numactl
命令能够查看这个分组状况。
# numactl --hardware
available: 2 nodes (0-1)
node 0 cpus: 0 1 2 3 4 5 12 13 14 15 16 17
node 0 size: 32756 MB
node 0 free: 19642 MB
node 1 cpus: 6 7 8 9 10 11 18 19 20 21 22 23
node 1 size: 32768 MB
node 1 free: 18652 MB
node distances:
node 0 1
0: 10 21
1: 21 10
经过上述命令能够看到,每一组CPU核分配了32GB(4条)的内存。 node distance
是一个二维矩阵,描述node访问全部内存条的延时状况。 node 0
里的CPU访问node 0
里的内存相对距离是10
,由于这时访问的内存都是和该CPU直连的。而node 0
若是想访问node 1
节点下的内存的话,就须要走QPI总线了,这时该相对距离就变成了21
。
因此、在NUMA架构下,CPU访问本身同一个node里的内存要比其它内存要快!
4动手测试NUMA架构内存延迟差别
numactl
命令有--cpubind
和--membind
的选项,经过它们咱们能够指定咱们要用的node节点。还沿用《实际测试内存在顺序IO和随机IO时的访问延时差别》里的测试代码
一、让内存和CPU处于同一个Node
下面代码可能须要左右滑动
# numactl --cpubind=0 --membind=0 ./main
Delay (ns)
2k 8k 32k 128k 512k 2m 8m 32m 128m
s1 1.28 1.28 1.26 1.25 1.26 1.26 1.28 1.43 1.43
s32 1.27 1.26 1.32 1.78 2.67 2.73 3.27 9.95 10.37
s64 1.28 1.26 1.26 1.82 2.43 2.48 3.15 8.82 8.92
random 2.40 2.40 2.40 2.40 4.80 4.80 19.20 28.80 52.80
二、让内存和CPU处于不一样Node
下面代码可能须要左右滑动
# numactl --cpubind=0 --membind=1 ./main
Delay (ns)
2k 8k 32k 128k 512k 2m 8m 32m 128m
s1 1.29 1.28 1.26 1.26 1.26 1.26 1.31 1.62 1.63
s32 1.29 1.26 1.33 1.77 2.80 2.92 3.95 13.69 13.77
s64 1.30 1.27 1.26 1.82 2.47 2.48 3.96 12.93 12.90
random 2.40 2.40 2.40 2.40 4.80 4.80 19.20 31.20 52.80
5结论
经过上面的各个小节咱们能够看到,现代的服务器里,CPU和内存条都有多个,它们以前目前主要采用的是复杂的NUMA架构进行互联,NUMA把服务器里的CPU和内存分组划分红了不一样的node。从上述实验结果来看,拿8M数组,循环步长为64的case来讲,同node耗时3.15纳秒,跨node为3.96纳秒。因此属于同一个node里的CPU和内存之间访问速度会比较快。而若是跨node的话,则须要通过QPI总线,整体来讲,速度会略慢一些。