前言 目前的主流服务器一般是二路,即有2个NUMA node。每个NUMA上有一个CPU。比较主流的CPU一般是10Core/12Core,打开了Hyper-thread的场景下,就是2 Sockets × 10/12 Cores/socket × 2 Hyper-threads/Core,也就是40核或者48核。 对于大规格的虚拟机,尤其是32 vCPU或者40vCPU的场景下,对于计算密集型的业务,需要把物理机的CPU拓扑信息正确的透传到虚拟机中,否则跨Socket的内存访问,同一个Core下的两个Hyper-thread的资源的争抢,都是影响性能的关键因素。 分析 Host上拓扑关系 我们一般会用lscpu命令看到基本的CPU拓扑信息,也可以通过cat /proc/cpuinfo的方式看到“physical id”,“core id” cpuid 再进一步探讨,Host kernle是怎么获取到的CPU的拓扑关系的呢? Linux有命令cpuid,代码在https://github.com/tycho/cpuid cpuid命令的结果截取如下:
可见,通过cpuid命令可以获取到cpu的确切的socket/core/thread信息。 进一步分析源代码可以发现,上图的打印信息是通过CPUID leaf 0x0b获取到的。 QEMU 既然是通过CPUID指令可以获取cpu的硬件拓扑,而且Guest在运行CPUID指令的时候,会从none-root模式退出来,hypervisor可以构造出来特定的reg参数告诉给Guest,这样,就可以让Guest正确获取到vCPU之间的拓扑关系了。 qemu支持了启动参数“sockets”,“cores”,“threads”。只能支持配置到sockets、cores和threads的数量。拓扑关系是不支持配置的,例如指定cpu0核cpu10是同一个core上的两个hyper-thread。 在qemu-2.12/include/hw/i386/topology.h的实现中:
可见,根据qemu的计算结果来看,cpu0和cpu1会在socket0的core0上。 物理机的拓扑有时候会是0,2,4,6。。。所以需要管控从Host上正确获取到cpu的拓扑,配置到读应的vcpu上。 Cache passthrough 同理,cache的拓扑关系也是通过CPUID leaf 0x02和leaf 0x04指令获取的,通过配置qemu的启动参数“host-cache-info=on”达到cpu cache的透传效果。