CPU 计算平台体系架构分为 SMP 体系架构和 NUMA 体系架构等,下图为 SMP 体系架构:node
SMP(Sysmmetric Multi-Processor System,对称多处理器系统),它由多个具备对称关系的处理器组成。所谓对称,即处理器之间是水平的镜像关系,没有主从之分。SMP 架构使得一台计算机再也不由单个 CPU 组成。数据库
SMP 的结构特征是多处理器共享一个集中式存储器,每一个处理器访问存储器的时间片一致,使工做负载可以均匀的分配到全部可用处理器上,极大地提升了整个系统的数据处理能力。可是,若是多个处理器同时请求访问共享资源时,就会引起资源竞争,须要软硬件实现加锁机制来解决这个问题。因此,SMP 又称为 UMA(Uniform Memory Access,一致性存储器访问),其中,一致性指的是在任意时刻,多个处理器只能为内存的每一个数据保存或共享一个惟一的数值。api
所以,这样的架构设计没法拥有良好的处理器数量扩展性,由于共享内存的资源竞态老是存在的,处理器利用率最好的状况只能停留在 2 到 4 颗。缓存
计算机系统中,处理器的处理速度要远快于内存的读写速度,因此限制计算机计算性能的瓶颈在存储器带宽上。SMP 架构由于限制了处理器访问存储器的频次,因此处理器可能会时刻对数据访问感到饥饿。架构
NUMA(Non-Uniform Memory Access,非一致性存储器访问)架构优化了 SMP 架构扩展性差以及存储器带宽窄的问题。socket
从上图能够看出,NUMA 和 SMP 架构是相似的,一样只会保存一份操做系统和数据库的副本,表示 NUMA 架构中的处理器依旧可以访问到整个存储器。两种主要的区别在于 NUMA 架构采用了分布式存储器,将处理器和存储器划分为不一样的节点(NUMA Node),每一个节点都包含了若干的处理器与内存资源。多节点的设计有效提升了存储器的带宽和处理器的扩展性。假设系统含有 4 个 NUMA 节点,那么在理想状况下系统的存储器带宽将会是 SMP 架构的 4 倍。分布式
另外一方面,NUMA 节点的处理器能够访问到总体存储器。按照节点内外,内存被分为节点内部的本地内存以及节点外部的远程内存。当处理器访问本地内存时,走的是内部总线,当处理器访问远程内存时,走的是主板上的 QPI 互联模块。访问前者的速度要远快于后者,NUMA(非一致性存储器访问)所以而得名。
性能
Thread: 使用超线程技术虚拟出来的逻辑 Core,须要 CPU 支持。为了便于区分,逻辑 Core 通常被写做 Processor。在具备 Intel 超线程技术的处理器上,每一个内核能够具备两个逻辑处理器,这两个逻辑处理器共享大多数内核资源(如内存缓存和功能单元)。此类逻辑处理器一般称为 Thread 。优化
上图的 NUMA Topology 有 2 个 NUMA node,每一个 node 有 1 个 socket,即 pCPU, 每一个 pCPU 有 6 个 core,1 个 core 有 2 个 Processor,则共有逻辑 cpu processor 24 个。ui
在 LIUNX 命令行中执行 lscpu 便可看到机器的 NUMA 拓扑结构:
如上图所示,机器有 2 个 node 分配到 2 个 socket 上,每一个 socket 有 14 个 core,每一个 core 有 2 个 processor, 则共有 56 个 cpu processor。同时,从上图也可看出 NUMA node 0 上的 cpu 分布为 0-13,28-41,而 node 1 上的分布为 14-27, 42-55。
由上节分析知,NUMA node 处理器访问本地内存的速度要快于访问远端内存的速度。访问速度与 node 的距离有关系,node 间的距离称为 node distance,使用 numactl --hardware 能够 show 出该距离:
node0 的本地内存大小为 32209MB,Node1 的本地内存大小为 32316MB。Node0 到本地内存的 distance 为 10,到 node1 的内存 distance 距离为 20。node1 到本地内存的 distance 为10,到 node0 的内存distance距离为20。
进一步对上面的 NUMA Topology 图进行介绍。
Liunx 上使用 cat /proc/cpuinfo 命令 show 出 cpu 信息:
其中 physical id 表示 socket 号。当前的 cpu core 是第 14 个 ,siblings 为 28 表示此 cpu14 在 core14 里面的兄弟逻辑 cpu 为 cpu28。CPU 14 和 CPU 28 共享 L1 Data cache、L1 instruction 和 L2 Cache 。
[***@controller-0 ~]$ cat /sys/devices/system/cpu/cpu14/cache/index0/type Data [***@controller-0 ~]$ cat /sys/devices/system/cpu/cpu14/cache/index1/type Instruction [***@controller-0 ~]$ cat /sys/devices/system/cpu/cpu14/cache/index2/type Unified [***@controller-0 ~]$ cat /sys/devices/system/cpu/cpu14/cache/index0/size 32K [***@controller-0 ~]$ cat /sys/devices/system/cpu/cpu14/cache/index1/size 32K [***@controller-0 ~]$ cat /sys/devices/system/cpu/cpu14/cache/index2/size 256K
cpu 绑核策略
对 Libvirt 驱动而言,虚拟机的 vCPU 能够绑定到主机的物理 CPU 上(pCPU)。这些配置能够改善虚拟机实例的精确度与性能。
openstack flavor set FLAVOR-NAME \ --property hw:cpu_policy=CPU-POLICY \ --property hw:cpu_thread_policy=CPU-THREAD-POLICY
有效的CPU-POLICY值为:
有效的 CPU-THREAD-POLICY 值为:
NUMA拓扑
Libvirt 驱动程序能够为虚拟机 vCPU 定义放置的 NUMA 节点,或者定义虚拟机从哪一个 NUMA 节点分配 vCPU 与内存。
$ openstack flavor set FLAVOR-NAME \ --property hw:numa_nodes=FLAVOR-NODES \ --property hw:numa_cpus.N=FLAVOR-CORES \ --property hw:numa_mem.N=FLAVOR-MEMORY
举例以下:
$ openstack flavor set aze-FLAVOR \ --property hw:numa_nodes=2 \ --property hw:numa_cpus.0=0,1 \ --property hw:numa_cpus.1=2,3 \ --property hw:numa_mem.0=2048 \ --property hw:numa_mem.1=2048 \
大页内存分配
$ openstack flavor set FLAVOR-NAME \
--property hw:mem_page_size=PAGE_SIZE
有效的 PAGE_SIZE 值为:
注意:大页内存能够分配给虚拟机内存,而不考虑 Guest OS 是否使用。若是 Guest OS 不使用大页内存,则它值会识别小页。反过来,若是 Guest OS 计划使用大页内存,则必定要给虚拟机分配大页内存。不然虚拟机的性能将不及预期。
Nova 实现 NUMA 流程以下所示:
1. nova-api 对 flavor metadata 或 image property 中的 NUMA 配置信息进行解析,生成 Guest NUMA topology,保存为 instance[‘numa_topology’]。
2. nova-scheduler 经过 NUMATopologyFilter 判断 Host NUMA topology 是否可以知足 Guest NUMA topology,进行 ComputeNode 调度。
3. nova-compute 再次经过 instance_claim 检查 Host NUMA 资源是否知足创建 Guest NUMA。
4. nova-compute 创建 Guest NUMA node 和 Host NUMA node 的映射关系,并根据映射关系调用 libvirt driver 生成 XML 文件。
5. Resource Tracker 会刷新 Host NUMA 资源的使用状况。