Red Hat Training

A Red Hat training course is available for RHEL 8

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

  1. 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>
  2. Optional: Pruebe el rendimiento de la máquina virtual utilizando las herramientas y utilidades aplicables.
  3. Configurar y montar páginas enormes de 1 GiB en el host:

    1. Añade la siguiente línea a la línea de comandos del kernel del host:

      default_hugepagesz=1G hugepagesz=1G
    2. 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
    3. 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.

    4. Haga ejecutable el script creado en el paso anterior:

      # chmod x /etc/systemd/hugetlb-reserve-pages.sh
    5. Habilitar la reserva de página enorme en el arranque:

      # systemctl enable hugetlb-gigantic-pages
  4. 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
  5. Ajuste la configuración XML de la VM de la siguiente manera:

    1. Configure la VM para utilizar 8 vCPUs estáticas. Utilice el elemento <vcpu/> para hacerlo.
    2. 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>
    3. Configura la VM para que utilice páginas enormes de 1 GiB:

      <memoryBacking>
        <hugepages>
          <page size='1' unit='GiB'/>
        </hugepages>
      </memoryBacking>
    4. 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>
    5. Asegúrese de que el modo de la CPU está configurado en host-passthrough, y que la CPU utiliza la caché en el modo passthrough:

      <cpu mode="host-passthrough">
        <topology sockets="2" cores="2" threads="2"/>
        <cache mode="passthrough"/>
  6. 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>
  7. 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'/>