16.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 nodeinfo
de 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 KiB
Usted 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 capabilities
La 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 máquina virtual 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=1G
Cree el archivo
/etc/systemd/system/hugetlb-gigantic-pages.service
con 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.target
Cree el archivo
/etc/systemd/hugetlb-reserve-pages.sh
con 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 node2
Esto 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.sh
Habilitar la reserva de página enorme en el arranque:
# systemctl enable hugetlb-gigantic-pages
Utilice el comando
virsh edit
para editar la configuración XML de la VM que desea optimizar, en este ejemplo super-VM:# virsh edit super-vm
Ajuste 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 capabilities
anterior, 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:
Tabla 16.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
Tabla 16.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
Tabla 16.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 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'/>