IOMMU调优: CPU pinning¶
为了使得PCI passthroughs 更为稳定和高性能,通过 CPU pinning
可以实现 NUMA架构 让处理器访问近端 PCIe 设备提高性能,同时也可以避免 缓存踩踏
导致性能下降。
原理¶
KVM guest默认是运行在和虚拟机相同县城数量,这些县城由Linux调度器按照优先级和等级队列调度到任何可用的CPU核心。这种方式下,如果线程被调度到不同的物理CPU就会导致本地CPU缓存(L1/L2/L3)失效,此时会明显影响虚拟机性能。CPU pinning就是针对这种虚拟CPU分配到物理CPU上运行的问题,设置两者的映射关系,尽可能减少缓存失效。此外,现代CPU通常使用一种共享的L3缓存,精心配置虚拟CPU和物理CPU的映射,可以使得L3缓存近端访问,降低缓存失效。
在完成 Open Virtual Machine Firmware(OMVF) 虚拟机设置添加NVMe pass-through 之后,从物理连接角度, HPE ProLiant DL360 Gen9服务器 的 PCIe 3.0 Slot 1 和 Slot 2 是和CPU 0(第一块CPU)直连的,所以最佳配置是将虚拟机的vcpu绑定到物理主机的 CPU 0
下的cpu core。
CPU拓扑¶
现代CPU处理器硬件都是多任务的,在Intel CPU称为超线程 hyper-threading
, AMD处理器称为 SMT
。检查CPU拓扑,采用以下命令:
lscpu -e
在 HPE ProLiant DL360 Gen9服务器 上 E5-2670 v3
处理器拓扑如下
1CPU NODE SOCKET CORE L1d:L1i:L2:L3 ONLINE MAXMHZ MINMHZ
2 0 0 0 0 0:0:0:0 yes 3100.0000 1200.0000
3 1 0 0 1 1:1:1:0 yes 3100.0000 1200.0000
4 2 0 0 2 2:2:2:0 yes 3100.0000 1200.0000
5 3 0 0 3 3:3:3:0 yes 3100.0000 1200.0000
6 4 0 0 4 4:4:4:0 yes 3100.0000 1200.0000
7 5 0 0 5 5:5:5:0 yes 3100.0000 1200.0000
8 6 0 0 6 6:6:6:0 yes 3100.0000 1200.0000
9 7 0 0 7 7:7:7:0 yes 3100.0000 1200.0000
10 8 0 0 8 8:8:8:0 yes 3100.0000 1200.0000
11 9 0 0 9 9:9:9:0 yes 3100.0000 1200.0000
12 10 0 0 10 10:10:10:0 yes 3100.0000 1200.0000
13 11 0 0 11 11:11:11:0 yes 3100.0000 1200.0000
14 12 1 1 12 12:12:12:1 yes 3100.0000 1200.0000
15 13 1 1 13 13:13:13:1 yes 3100.0000 1200.0000
16 14 1 1 14 14:14:14:1 yes 3100.0000 1200.0000
17 15 1 1 15 15:15:15:1 yes 3100.0000 1200.0000
18 16 1 1 16 16:16:16:1 yes 3100.0000 1200.0000
19 17 1 1 17 17:17:17:1 yes 3100.0000 1200.0000
20 18 1 1 18 18:18:18:1 yes 3100.0000 1200.0000
21 19 1 1 19 19:19:19:1 yes 3100.0000 1200.0000
22 20 1 1 20 20:20:20:1 yes 3100.0000 1200.0000
23 21 1 1 21 21:21:21:1 yes 3100.0000 1200.0000
24 22 1 1 22 22:22:22:1 yes 3100.0000 1200.0000
25 23 1 1 23 23:23:23:1 yes 3100.0000 1200.0000
26 24 0 0 0 0:0:0:0 yes 3100.0000 1200.0000
27 25 0 0 1 1:1:1:0 yes 3100.0000 1200.0000
28 26 0 0 2 2:2:2:0 yes 3100.0000 1200.0000
29 27 0 0 3 3:3:3:0 yes 3100.0000 1200.0000
30 28 0 0 4 4:4:4:0 yes 3100.0000 1200.0000
31 29 0 0 5 5:5:5:0 yes 3100.0000 1200.0000
32 30 0 0 6 6:6:6:0 yes 3100.0000 1200.0000
33 31 0 0 7 7:7:7:0 yes 3100.0000 1200.0000
34 32 0 0 8 8:8:8:0 yes 3100.0000 1200.0000
35 33 0 0 9 9:9:9:0 yes 3100.0000 1200.0000
36 34 0 0 10 10:10:10:0 yes 3100.0000 1200.0000
37 35 0 0 11 11:11:11:0 yes 3100.0000 1200.0000
38 36 1 1 12 12:12:12:1 yes 3100.0000 1200.0000
39 37 1 1 13 13:13:13:1 yes 3100.0000 1200.0000
40 38 1 1 14 14:14:14:1 yes 3100.0000 1200.0000
41 39 1 1 15 15:15:15:1 yes 3100.0000 1200.0000
42 40 1 1 16 16:16:16:1 yes 3100.0000 1200.0000
43 41 1 1 17 17:17:17:1 yes 3100.0000 1200.0000
44 42 1 1 18 18:18:18:1 yes 3100.0000 1200.0000
45 43 1 1 19 19:19:19:1 yes 3100.0000 1200.0000
46 44 1 1 20 20:20:20:1 yes 3100.0000 1200.0000
47 45 1 1 21 21:21:21:1 yes 3100.0000 1200.0000
48 46 1 1 22 22:22:22:1 yes 3100.0000 1200.0000
49 47 1 1 23 23:23:23:1 yes 3100.0000 1200.0000
按照 NUMA架构 执行:
numactl -H
在 HPE ProLiant DL360 Gen9服务器 上 E5-2670 v3
处理器NUMA结构如下
1available: 2 nodes (0-1)
2node 0 cpus: 0 1 2 3 4 5 6 7 8 9 10 11 24 25 26 27 28 29 30 31 32 33 34 35
3node 0 size: 32093 MB
4node 0 free: 30201 MB
5node 1 cpus: 12 13 14 15 16 17 18 19 20 21 22 23 36 37 38 39 40 41 42 43 44 45 46 47
6node 1 size: 32250 MB
7node 1 free: 29059 MB
8node distances:
9node 0 1
10 0: 10 21
11 1: 21 10
请注意:
默认开启了超线程,所以一个CPU核心对应了2个超线程,为了最大化存储性能,需要将负载高的存储虚拟机分配到不同到CPU核心(超线程不冲突)
物理服务器上安装了2个CPU(socket),
SOCKET 0
对应了CPU 0,SOCKET 1
对应了CPU 1,也就是node 0
和node 1
; 在numactl -H
输出中可以清晰看到:node 0 cpus: 0 1 2 3 4 5 6 7 8 9 10 11 24 25 26 27 28 29 30 31 32 33 34 35 node 1 cpus: 12 13 14 15 16 17 18 19 20 21 22 23 36 37 38 39 40 41 42 43 44 45 46 47
由于 HPE ProLiant DL360 Gen9服务器 只在
Slot 1
提供了 PCIe bifurcation ,所以我把2块 三星PM9A1 NVMe存储 通过NVMe扩展卡安装在Slot 1
,把第3块 三星PM9A1 NVMe存储 安装在Slot 2
。这意味着,服务器的3块NVMe存储都是直接和node 0
连接的,所以对应虚拟机也要pinning
到这个CPU 0
上,也就是CPU超线程0 - 11
和24 - 35
。这两组CPU超线程实际上对应的物理CPU core一共是12个。我分配的
z-b-data-X
虚拟机共3个,采用4c8g
规格,分配到 CPU 超线程24 - 35
可以确保不重合,性能最大化
配置cpu pinning¶
修订
z-b-data-1
(举例)sudo virsh edit z-b-data-1
设置 vcpu
和 cpuset
对应映射关系:
<vcpu placement='static'>4</vcpu>
<cputune>
<vcpupin vcpu='0' cpuset='24'/>
<vcpupin vcpu='1' cpuset='25'/>
<vcpupin vcpu='2' cpuset='26'/>
<vcpupin vcpu='3' cpuset='27'/>
</cputune>
然后启动虚拟机:
sudo virsh start z-b-data-1
通过 比较IOMMU NVMe和原生NVMe存储性能 ,可以看到 fio 存储性能测试 启动4个jobs,物理服务器上繁忙的CPU就是
24 - 27