http://bbs.qy.com.cn/thread-1111-1-1.html
一、 NUMA
1. NUMA 介绍
早期的时候,每台服务器都是单CPU,随着技术的发展,出现了多CPU共同工作的需求。
NUMA(Non-Uniform Memory Access,非一致性内存访问)和SMP(Symmetric Multi-Processor,对称多处理器系统)是两种不同的解决多CPU共同工作的硬件体系架构。
SMP的主要特征是共享,所有的CPU共享使用全部资源,例如内存、总线和I/O,多个CPU对称工作,彼此之间没有主次之分,平等地访问共享的资源,这样势必引入资源的竞争问题,从而导致它的扩展内力非常有限。
NUMA技术将CPU划分成不同的组(Node),每个Node由一个或多个(物理)CPU组成,并且有独立的本地内存、I/O等资源。Node之间通过互联模块连接和沟通,因此除了本地内存外,每个CPU仍可以访问远端Node的内存,只不过效率会比访问本地内存差一些。(我们用Node之间的距离Distance来定义各个Node之间互访资源的开销。)所以,NUMA调优的目的是让处理器尽量访问自己的存储器,以提高处理速度。
NUMA支持的软硬件要求:
硬件方面,英特尔从Xeon(至强)5500 处理器开始采用NUMA架构。
软件方面,Windows Server 2003 和Windows XP 64-bit Edition, Windows XP等都是NUMA aware的,而Windows Vista/7/2008 Server则有了对Numa调度的支持。所有使用2.6版本以上kernel的Linux操作系统都能够支持NUMA。而Solaris,HP-Unix等UNIX操作系统也是充分支持NUMA架构的。对于数据库来说,SQL Server 2005 开始支持NUMA的支持。
Linux下,使用命令numactl --hardware 查看当前物理CPU的numa情况:
- [root@qycn46 ~]# numactl --hardware
- available: 2 nodes (0-1) # 本服务器有两个node,分别为node0 和 node1
- node 0 cpus: 0 1 2 3 # node 0 包含的CPU
- node 0 size: 16375 MB # node 0 的内存16G
- node 0 free: 2616 MB
- node 1 cpus: 4 5 6 7 # node 1 包含的CPU
- node 1 size: 16384 MB # node 1 的内存16G
- node 1 free: 2118 MB
- node distances:
- node 0 1
- 0: 10 21 # node内访问内存的distance是10,跨node访问的distance为21
- 1: 21 10 # 远端访问的开销是本地访问的2.1倍
- [root@qycn46 ~]#
2. CPU Topology
在NUMA架构下,CPU的概念从大到小依次是:Node、Socket、Core、Processor。
随着多核技术的发展,我们将多个CPU封装在一起,这个封装一般被称为Socket(插槽),而Socket中的每个核心被称为Core。为了进一步提升CPU的处理能力,Intel又引入了HT(Hyper-Threading,超线程)的技术,一个Core打开HT之后,在OS看来就是两个核,当然这个核是逻辑上的概念,所以也被称为Logical Processor,本文简称为Processor。
综上所述,一个NUMA Node可以有一个或者多个Socket,一个多核Socket显然包含多个Core,一个Core如果打开HT则变成两个Logical Processor。
Linux中,CPU的Socket, Core, Processor 信息都可以通过 /proc/cpuinfo 文档查询,这里列出实验物理机的cpu特性如下:
3. NUMA调度优化
查看虚拟机的NUMA配置
- [root@qycn46 ~]# virsh list --all
- Id Name State
- ----------------------------------------------------
- 3 VM3 running
- 16 test running
- - VM1 shut off
- [root@qycn46 ~]# virsh numatune test
- numa_mode : strict
- numa_nodeset : 0-1
- [root@qycn46 ~]#
这里需要注意,如果<numatune> 设置了placement='auto',则<vcpu>的placement 也应为auto,如下图所示。
可以使用以下命令来设置将虚拟机绑定到指定node。
- virsh numatune domain --nodeset 'string'
举个列子:将上面的虚拟机test(6核),限定在Node0和1中,使用物理机六个CPU1,2,3,4,6,7。
(注:本例中由于一个socket仅有4个CPU,不能满足虚拟机 test的需求,所以例子对NUMA性能并没有改善,但这里的重点是示范操作过程。)
a. 先观察未做NUMA设置之前,虚拟机test对物理机CPU的使用情况:
b. virsh numatune test --nodeset '0-1'
c. 打开虚拟机配置文件,在<vcpu> 部分添加 cpuset='1-7,^5'
d. 重启虚拟机(不知道怎样不重启就立即生效,后续再研究。。。),再次查看虚拟机CPU情况:
可以发现,设置后,虚拟机vcpu仅运行在物理机CPU1-4和6-7中。
( 假如本例中的服务器CPU支持超线程,则一个socket就有8个CPU,这样,我们就可以将虚拟机test的6核限定在一个socket(一个Node)内,使用最小的distance10开销,这样就提高了效率。)
什么是 CPU Affinity (处理器亲和性)?
进程的处理器亲和性,即是CPU的绑定设置,是指将进程绑定到特定的一个或多个CPU上去执行,而不允许调度到其他的CPU上。
设置进程的处理器亲和性带来的好处是可以减少进程在多个CPU之间交换运行带来的缓存命中失效(cache missing),从该进程运行的角度来看,可能带来一定程度上的性能提升。换个角度来看,对进程亲和性的设置也可能带来一定的问题,如破坏了系统对各CPU的负载均衡,这有可能会导致整个系统的进程调度变得低效。
对虚拟机<vcpu> 中的cpuset做配置,会体现在CPU Affinity中。
二、 虚拟机VCPU的绑定
CPU绑定规则:
从大的范围来看,虚拟机所有的VCPU应尽可能在同一个Node内,减少内存访问开销。细化下来,对于物理 CPU,同一个 core 的 threads 共享 L2 Cache,同一个 socket 的 cores 共享 L3 cache,所以虚拟机的 VCPU 也应当尽可能在同一个 core 和 同一个 socket 中,增加 cache 的命中率,从而提高性能。所以,具体的绑定策略,应该根据宿主机物理CPU特性和虚拟机VCPU个数来定。
(1) VCPU个数不大于2个,且物理机CPU支持超线程,则可以将VCPU绑定到同一个core内。
(2) VCPU个数不大于物理机一个Socket的总逻辑Processor个数,则可以将VCPU绑定到同一个Socket中。
(3) VCPU个数不大于物理机一个Node的总逻辑Processor个数,则可以将VCPU绑定到同一个Node中。
(4) 根据实际情况,物理机某Processor使用率很高导致虚拟机很卡,则可及时将虚拟机绑定到物理机其他较空闲的Processor。
CPU在线绑定方法:
1. 区域绑定
(注意:继续下面的实验前,请先取消上面的NUMA设置及对<vcpu>中cpuset的设置,否则下面的设置将不生效。)
Emulator标签可以为虚拟机指定物理机的任意逻辑Processor, 下面的指令可以 在线调整CPU绑定情况。
- virsh emulatorpin domain 'string'
b. 修改emulator的设置 virsh emulatorpin test '1-4,6-7',再查看虚拟机VCPU状态
由上图发现,emulator的设置似乎没有生效,因为VCPU3竟然运行在物理机CPU5上,而CPU5在上面的设置中是排除了的。
还需继续实验验证是哪里的问题。 ?????
c. 查看emulatorpin的在xml文件中的表现形式:
(内存中的xml文件[virsh dumpxml domain]已经更改,但virsh edit domain 查看配置文件还未改变,所以每次通过指令virsh emulatorpin变更CPU绑定后,都需要将内存中的<cputune>设置copy到xml中并保存。)
2. 一对一绑定
可以使用 virsh vcpupin 指令强制VCPU与物理逻辑Processor一对一绑定,具体指令如下:
- virsh vcpupin domain vcpu# Processor#
- virsh vcpupin test 0 1
- virsh vcpupin test 1 2
- virsh vcpupin test 2 3
- virsh vcpupin test 3 4
- virsh vcpupin test 4 6
- virsh vcpupin test 5 7
查看一下vcpupin设置在xml文件中的表现形式:
(同样的,内存中的xml文件[virsh dumpxml domain]已经更改,但virsh edit domain 查看配置文件还未改变,所以每次通过指令virsh vcpupin变更CPU绑定后,都需要将内存中的<cputune>设置copy到xml中并保存。)
三、 虚拟机多VCPU的设定方法
可参考 KVM虚拟机操作常见问题 的第一条
四、在线添加CPU
(1) 在创建CPU的时候,设置maxvcpu参数,且当前vcpu数量小于maxvcpu数量,即可使用
- virsh setvcpus domain cpunum# --live
如图,虚拟机tst当前CPU个数为3,设置后,CPU数目动态变为4个。
查看该配置在xml 中的表现形式:
(同样的,内存中的xml文件[virsh dumpxml domain]已经更改,但virsh edit domain 查看配置文件还未改变,所以每次通过指令virsh setvcpus变更CPU数量后,都需要将内存中的<vcpu>设置中的current 数量修改到xml中并保存。)
(2) 也可以直接按上图所示格式修改虚拟机的配置文件xml。
a. 在<vcpu> 内添加currrent 参数,后接虚拟机当前VCPU数量(也可以为希望调整的VCPU数量),两个尖括号中间的值为最大VCPU数量(需不小于current数量)。
b. 重启虚拟机,此时最大VCPU的设置生效。
c. 后续若需要再次调整CPU数目,使用virsh setvcpus tst # --live 即可。
注意:centos6.7 系统的宿主机和虚拟机上,可在最大VCPU范围内随意更改VCPU个数,但是在centos7.1 系统的宿主机和虚拟机上,VCPU个数只能增加,不能减少。
综上所述,如果想在线添加VCPU数量,还是要未雨绸缪,在创建虚拟机时就先设置好 maxvcpu 参数,这样后面修改时才不必重启虚拟机。