11.5.4. Ejemplo de escenario de ajuste de rendimiento de vCPU
Para obtener el mejor rendimiento posible de la vCPU, Red Hat recomienda utilizar los ajustes manuales vcpupin, emulatorpin, y numatune juntos, por ejemplo como en el siguiente escenario.
Escenario de partida
Su host tiene las siguientes características de hardware:
- 2 nodos NUMA
- 3 núcleos de CPU en cada nodo
- 2 hilos en cada núcleo
La salida de
virsh nodeinfode una máquina de este tipo sería similar:# virsh nodeinfo CPU model: x86_64 CPU(s): 12 CPU frequency: 3661 MHz CPU socket(s): 2 Core(s) per socket: 3 Thread(s) per core: 2 NUMA cell(s): 2 Memory size: 31248692 KiBUsted pretende modificar una VM existente para que tenga 8 vCPUs, lo que significa que no cabrá en un solo nodo NUMA.
Por lo tanto, debes distribuir 4 vCPUs en cada nodo NUMA y hacer que la topología de las vCPUs se parezca lo más posible a la topología del host. Esto significa que las vCPUs que se ejecutan como hilos hermanos de una determinada CPU física deben estar vinculadas a los hilos del host en el mismo núcleo. Para más detalles, consulte la página web Solution:
Solución
Obtenga la información sobre la topología del host:
# virsh capabilitiesLa salida debe incluir una sección similar a la siguiente:
<topology> <cells num="2"> <cell id="0"> <memory unit="KiB">15624346</memory> <pages unit="KiB" size="4">3906086</pages> <pages unit="KiB" size="2048">0</pages> <pages unit="KiB" size="1048576">0</pages> <distances> <sibling id="0" value="10" /> <sibling id="1" value="21" /> </distances> <cpus num="6"> <cpu id="0" socket_id="0" core_id="0" siblings="0,3" /> <cpu id="1" socket_id="0" core_id="1" siblings="1,4" /> <cpu id="2" socket_id="0" core_id="2" siblings="2,5" /> <cpu id="3" socket_id="0" core_id="0" siblings="0,3" /> <cpu id="4" socket_id="0" core_id="1" siblings="1,4" /> <cpu id="5" socket_id="0" core_id="2" siblings="2,5" /> </cpus> </cell> <cell id="1"> <memory unit="KiB">15624346</memory> <pages unit="KiB" size="4">3906086</pages> <pages unit="KiB" size="2048">0</pages> <pages unit="KiB" size="1048576">0</pages> <distances> <sibling id="0" value="21" /> <sibling id="1" value="10" /> </distances> <cpus num="6"> <cpu id="6" socket_id="1" core_id="3" siblings="6,9" /> <cpu id="7" socket_id="1" core_id="4" siblings="7,10" /> <cpu id="8" socket_id="1" core_id="5" siblings="8,11" /> <cpu id="9" socket_id="1" core_id="3" siblings="6,9" /> <cpu id="10" socket_id="1" core_id="4" siblings="7,10" /> <cpu id="11" socket_id="1" core_id="5" siblings="8,11" /> </cpus> </cell> </cells> </topology>- Optional: Pruebe el rendimiento de la VM utilizando las herramientas y utilidades aplicables.
Configurar y montar páginas enormes de 1 GiB en el host:
Añade la siguiente línea a la línea de comandos del kernel del host:
default_hugepagesz=1G hugepagesz=1GCree el archivo
/etc/systemd/system/hugetlb-gigantic-pages.servicecon el siguiente contenido:[Unit] Description=HugeTLB Gigantic Pages Reservation DefaultDependencies=no Before=dev-hugepages.mount ConditionPathExists=/sys/devices/system/node ConditionKernelCommandLine=hugepagesz=1G [Service] Type=oneshot RemainAfterExit=yes ExecStart=/etc/systemd/hugetlb-reserve-pages.sh [Install] WantedBy=sysinit.targetCree el archivo
/etc/systemd/hugetlb-reserve-pages.shcon el siguiente contenido:#!/bin/sh nodes_path=/sys/devices/system/node/ if [ ! -d $nodes_path ]; then echo "ERROR: $nodes_path does not exist" exit 1 fi reserve_pages() { echo $1 > $nodes_path/$2/hugepages/hugepages-1048576kB/nr_hugepages } reserve_pages 4 node1 reserve_pages 4 node2Esto reserva cuatro páginas enormes de 1GiB de node1 y cuatro páginas enormes de 1GiB de node2.
Haga ejecutable el script creado en el paso anterior:
# chmod x /etc/systemd/hugetlb-reserve-pages.shHabilitar la reserva de página enorme en el arranque:
# systemctl enable hugetlb-gigantic-pages
Utilice el comando
virsh editpara editar la configuración XML de la VM que desea optimizar, en este ejemplo super-VM:# virsh edit super-vmAjuste la configuración XML de la VM de la siguiente manera:
-
Configure la VM para utilizar 8 vCPUs estáticas. Utilice el elemento
<vcpu/>para hacerlo. Conecte cada uno de los hilos de la vCPU a los correspondientes hilos de la CPU del host que refleja en la topología. Para ello, utilice los elementos de
<vcpupin/>en la sección<cputune>.Tenga en cuenta que, como se muestra en la utilidad
virsh capabilitiesanterior, los hilos de la CPU del host no están ordenados secuencialmente en sus respectivos núcleos. Además, los hilos de la vCPU deben fijarse en el conjunto más alto de núcleos de host disponibles en el mismo nodo NUMA. Para ver una ilustración de la tabla, consulte la sección Additional Resources a continuación.La configuración XML para los pasos a. y b. puede ser similar a
<cputune> <vcpupin vcpu='0' cpuset='1'/> <vcpupin vcpu='1' cpuset='4'/> <vcpupin vcpu='2' cpuset='2'/> <vcpupin vcpu='3' cpuset='5'/> <vcpupin vcpu='4' cpuset='7'/> <vcpupin vcpu='5' cpuset='10'/> <vcpupin vcpu='6' cpuset='8'/> <vcpupin vcpu='7' cpuset='11'/> <emulatorpin cpuset='6,9'/> </cputune>Configura la VM para que utilice páginas enormes de 1 GiB:
<memoryBacking> <hugepages> <page size='1' unit='GiB'/> </hugepages> </memoryBacking>Configure los nodos NUMA de la máquina virtual para que utilicen la memoria de los nodos NUMA correspondientes del host. Para ello, utilice los elementos de
<memnode/>en la sección<numatune/>:<numatune> <memory mode="preferred" nodeset="1"/> <memnode cellid="0" mode="strict" nodeset="0"/> <memnode cellid="1" mode="strict" nodeset="1"/> </numatune>Asegúrese de que el modo de la CPU está configurado en
host-passthrough, y que la CPU utiliza la caché en el modopassthrough:<cpu mode="host-passthrough"> <topology sockets="2" cores="2" threads="2"/> <cache mode="passthrough"/>
-
Configure la VM para utilizar 8 vCPUs estáticas. Utilice el elemento
La configuración XML resultante de la VM debe incluir una sección similar a la siguiente:
[...] <memoryBacking> <hugepages> <page size='1' unit='GiB'/> </hugepages> </memoryBacking> <vcpu placement='static'>8</vcpu> <cputune> <vcpupin vcpu='0' cpuset='1'/> <vcpupin vcpu='1' cpuset='4'/> <vcpupin vcpu='2' cpuset='2'/> <vcpupin vcpu='3' cpuset='5'/> <vcpupin vcpu='4' cpuset='7'/> <vcpupin vcpu='5' cpuset='10'/> <vcpupin vcpu='6' cpuset='8'/> <vcpupin vcpu='7' cpuset='11'/> <emulatorpin cpuset='6,9'/> </cputune> <numatune> <memory mode="preferred" nodeset="1"/> <memnode cellid="0" mode="strict" nodeset="0"/> <memnode cellid="1" mode="strict" nodeset="1"/> </numatune> <cpu mode="host-passthrough"> <topology sockets="2" cores="2" threads="2"/> <cache mode="passthrough"/> <numa> <cell id="0" cpus="0-3" memory="2" unit="GiB"> <distances> <sibling id="0" value="10"/> <sibling id="1" value="21"/> </distances> </cell> <cell id="1" cpus="4-7" memory="2" unit="GiB"> <distances> <sibling id="0" value="21"/> <sibling id="1" value="10"/> </distances> </cell> </numa> </cpu> </domain>- Optional: Pruebe el rendimiento de la VM utilizando las herramientas y utilidades aplicables para evaluar el impacto de la optimización de la VM.
Recursos adicionales
Las siguientes tablas ilustran las conexiones entre las vCPUs y las CPUs anfitrionas a las que deben ser fijadas:
Expand Tabla 11.1. Topología de host CPU threads
0
3
1
4
2
5
6
9
7
10
8
11
Cores
0
1
2
3
4
5
Sockets
0
1
NUMA nodes
0
1
Expand Tabla 11.2. Topología VM vCPU threads
0
1
2
3
4
5
6
7
Cores
0
1
2
3
Sockets
0
1
NUMA nodes
0
1
Expand Tabla 11.3. Topología combinada de host y VM vCPU threads
0
1
2
3
4
5
6
7
Host CPU threads
0
3
1
4
2
5
6
9
7
10
8
11
Cores
0
1
2
3
4
5
Sockets
0
1
NUMA nodes
0
1
En este escenario, hay 2 nodos NUMA y 8 vCPUs. Por lo tanto, 4 hilos de vCPU deben ser fijados a cada nodo.
Además, Red Hat recomienda dejar al menos un hilo de CPU disponible en cada nodo para las operaciones del sistema anfitrión.
Como en este ejemplo, cada nodo NUMA alberga 3 núcleos, cada uno de ellos con 2 hilos de la CPU anfitriona, el conjunto para el nodo 0 se traduce como sigue:
<vcpupin vcpu='0' cpuset='1'/> <vcpupin vcpu='1' cpuset='4'/> <vcpupin vcpu='2' cpuset='2'/> <vcpupin vcpu='3' cpuset='5'/>