EPYC: cómo AMD convirtió los servidores en una sala de exposición

¿Te fue útil?

Compras un servidor esperando que se comporte como un electrodoméstico fiable: latencias predecibles, gráficas aburridas, sin sorpresas a las 2 a. m.
Luego montas una máquina AMD EPYC, enciendes unas decenas de máquinas virtuales, añades NVMe, y de repente tu visita al centro de datos suena como un vendedor de coches:
“Mira todos estos núcleos. Mira las líneas. Mira los canales de memoria.”

El problema es que las salas de exposición están optimizadas para causar asombro. La producción está optimizada para “no ocurra nada raro”.
EPYC puede hacer ambas cosas, pero solo si entiendes lo que cambió en el diseño de servidores —y dónde están los bordes afilados cuando tu carga de trabajo choca con NUMA, la topología PCIe
y una pila de almacenamiento que nunca pidió tantos colas en paralelo.

Por qué EPYC hizo que los servidores se vieran distintos

EPYC no solo dio a los operadores más núcleos. Cambió cómo se ve un servidor “balanceado”. Durante mucho tiempo, el diseño de servidores fue
un conjunto de compromisos que todos aceptaban: pocas lanes PCIe, canales de memoria que se llenaban demasiado rápido y CPUs que te obligaban
a configuraciones de doble socket caras solo para obtener E/S.

EPYC llegó y convirtió los servidores mono-socket en la opción adulta en lugar de la opción económica. Más lanes PCIe significaron que
podías conectar NVMe serios sin jugar al Tetris. Más canales de memoria significaron que podías alimentar esos núcleos sin quedarte inmediatamente sin
ancho de banda. Y el enfoque chiplet permitió a AMD escalar los conteos de núcleos sin necesitar un dado monolítico del tamaño de tu arrepentimiento.

El efecto sala de exposición es real: ahora puedes construir una máquina que en papel parece absurda —docenas de núcleos, una pared de NVMe y suficiente
ancho de banda de memoria para hacer sudar a arquitecturas antiguas. Pero la sala de exposición tiene una sombra: si ignoras la topología, crearás
cuellos de botella que no aparecen en benchmarks simples y solo emergen cuando todo está ruidoso a la vez.

Hechos y contexto que explican el cambio

Aquí tienes datos históricos y de contexto concretos que ayudan a explicar por qué EPYC se sintió como un reinicio de mercado, no como un lanzamiento normal.
No son trivialidades. Se traducen en decisiones de diseño que tomarás en racks y en hojas de cálculo de compras.

  1. 2017 fue el punto de inflexión: EPYC “Naples” (1.ª gen) llegó y obligó a los compradores a reconsiderar la densidad en un solo socket como una opción de primera clase.
  2. Los chiplets se volvieron mainstream en servidores: el diseño multi-die de EPYC normalizó la idea de que la latencia y la localidad importan más que la «pureza» de un solo dado grande.
  3. Los canales de memoria volvieron a ser criterio de compra: las amplias configuraciones de memoria de EPYC llevaron el “ancho de banda por dólar” a la sala de juntas.
  4. El recuento de lanes PCIe dejó de ser un error de redondeo: plataformas con muchas lanes habilitaron más NVMe y más NICs sin CPUs adicionales.
  5. Rome (2.ª gen) presionó fuerte los conteos de núcleos: cuando suben los núcleos, las licencias por software y la sobrecarga por núcleo se convierten en riesgos operativos, no solo en partidas presupuestarias.
  6. Milan (3.ª gen) mejoró latencia e IPC: no fue solo más núcleos; mejoró el comportamiento single-thread lo suficiente como para importar en bases de datos y planos de control.
  7. Genoa (4.ª gen) movió otra vez la meta de E/S: DDR5 y PCIe Gen5 elevaron el techo, pero también hicieron que las decisiones de layout y refrigeración fueran más relevantes.
  8. Los proveedores cloud lo validaron públicamente: grandes despliegues señalaron “esto no es nicho”, y eso importa cuando compras en un ecosistema de firmware, placas y soporte.

Arquitectura que puedes usar de verdad (chiplets, NUMA, E/S)

Chiplets: lo que todos repiten, y lo que realmente importa

“Chiplets” se vende como si fuera una elección de estilo de vida. En producción, es una historia de topología. Múltiples dies de cómputo (CCDs) cuelgan de un die de E/S,
y tus hilos, asignaciones de memoria e interrupciones ahora participan en una lección de geografía. La CPU ya no es un solo vecindario;
es una ciudad con puentes.

Eso impacta tres cosas que no puedes ignorar:

  • Localidad NUMA: la memoria conectada a un nodo no es igual de rápida desde otro. La penalización varía según generación y configuración, pero nunca es cero.
  • Comportamiento de caché: una caché agregada mayor no significa que tus datos calientes estén cerca de tu hilo. “Cerca” ahora es una propiedad técnica, no una sensación.
  • Jitter bajo carga: cuando la interconexión está ocupada—mucha E/S, muchos núcleos, muchas interrupciones—la latencia de cola es donde pagarás.

NUMA: no puedes «apagarlo», solo faltarle al respeto

NUMA no es un error. Es un contrato. Si colocas memoria y cómputo en el mismo nodo, obtienes mejor latencia y ancho de banda. Si no lo haces, pagas un impuesto de rendimiento.
Ese impuesto a veces es barato de ignorar. A veces es todo tu incidente.

Las plataformas EPYC comúnmente exponen múltiples nodos NUMA por socket dependiendo de ajustes como NPS (NUMA por socket) y cómo el kernel enumera la E/S.
Puedes afinar para menos dominios NUMA (planificación más simple, potencialmente mayor contención local) o más dominios (más oportunidades de localidad,
más complejidad).

Die de E/S y abundancia de lanes: la trampa oculta

EPYC hizo que la E/S pareciera «resuelta» porque puedes conectar muchos dispositivos. Pero “recuento de lanes” no es lo mismo que “E/S sin contención”.
Switches, bifurcación, valores por defecto del firmware y el enrutamiento de interrupciones del kernel aún pueden convertir una topología gloriosa en un estacionamiento.

La otra trampa es psicológica: los equipos empiezan a conectar todo porque pueden. Más NVMe. Más NICs. Más HBAs “por si acaso”.
Entonces la plataforma se convierte en un experimento de bus compartido y te sorprende que la QoS sea difícil.

Broma #1: Un servidor con 128 lanes no es “a prueba de futuro”. Es “resistente a la tentación del futuro”, y la mayoría de nosotros falla la prueba.

Virtualización y consolidación: lo bueno, lo raro, lo arreglable

EPYC es una máquina de consolidación. Si ejecutas una granja de VMs con muchas VMs “medianas”, puedes aumentar la densidad sin el clásico impuesto del doble socket.
Pero la consolidación es donde el efecto sala de exposición muerde: cuanto más empaquetas, más amplificas efectos de planificador y memoria que antes pasaban desapercibidos.

La densidad de núcleos cambia los modos de fallo

Cuando pasas de “unas pocas docenas de hilos” a “cientos de hilos ejecutables”, tus cuellos de botella cambian:

  • La CPU no es el límite; es el ancho de banda de memoria. Especialmente para analítica, compresión, cifrado y pilas de almacenamiento con muchas copias.
  • El manejo de interrupciones importa otra vez. Una NIC rápida con mala afinidad de IRQ puede parecer un problema de CPU mientras tus núcleos giran en softirqs.
  • La contención de locks se hace visible. Algunos softwares escalan hasta 64 núcleos y luego se estrellan a 96 porque un lock global se convierte en un torniquete.

Licencias y realidades “por núcleo”

Tu equipo de compras adorará los altos conteos de núcleos hasta que no. Algunos softwares empresariales aún cobran por núcleo, por socket,
por vCPU o con matemáticas de factores por núcleo diseñadas para hacerte sentir mal. EPYC facilita comprar más computo del que puedes licenciar sensatamente.

Consejo operativo: trata la licenca como una restricción de rendimiento. Si no puedes permitirte usar todos los núcleos, no finjas que los tienes.
Establece límites de CPU realistas, haz pinning cuando sea necesario y evita construir una arquitectura que dependa de “la licenciamos después”.

Cuando el pinning es inteligente y cuando es cosplay

El pinning de CPU y el pinning NUMA son herramientas poderosas. También son una excelente forma de convertir tu plataforma de virtualización en una hoja de cálculo mantenida a mano
que se rompe cada vez que añades una NIC.

El pinning vale la pena cuando:

  • tienes cargas sensibles a la latencia (sistemas de trading, planos de control casi en tiempo real, ciertas bases de datos)
  • tienes hosts dedicados para pocas VMs grandes
  • puedes imponer una colocación consistente y mantener el drift del host bajo control

El pinning suele ser un error cuando:

  • el entorno es altamente dinámico (autoscaling, evacuaciones frecuentes)
  • la carga está orientada a throughput y tolera la variación
  • el equipo no tiene observabilidad de misses NUMA y hotspots de interrupciones

Almacenamiento y PCIe: lanes no son rendimiento

La historia más común de EPYC en almacenamiento es simple: “Conectamos muchos NVMe y esperábamos escalado lineal.” A veces lo consigues.
A menudo obtienes una meseta confusa. La meseta no es un fracaso moral. Es la combinación de:

  • Localidad NUMA (tus interrupciones NVMe se manejan lejos de los hilos de la aplicación)
  • Topología PCIe (uplinks de switch, bifurcación, oversubscription)
  • profundidades de cola y elecciones del scheduler de IO
  • comportamiento del sistema de ficheros y RAID/ZFS bajo cargas mixtas
  • interacciones de la pila red/almacenamiento (especialmente en Ceph, iSCSI, NVMe-oF)

Paralelismo NVMe: la CPU entra en la ruta de almacenamiento

NVMe es rápido porque es paralelo. Eso significa más colas, más interrupciones, más tiempo de CPU en el kernel.
En EPYC tienes muchos núcleos para dedicarle —pero aún necesitas colocar ese trabajo cerca del nodo NUMA correcto,
y asegurarte de que no estás limitado por una sola cola, una sola IRQ o una sola CPU manejando softirqs.

Ancho de banda de memoria: el limitador silencioso para almacenamiento

El almacenamiento de alta velocidad a menudo se convierte en “qué tan rápido podemos mover memoria”. Checksums, compresión, cifrado, replicación
e incluso copiado simple pueden saturar el ancho de banda de memoria mucho antes de que el “uso de CPU” luzca alarmante. Los canales de memoria de EPYC ayudan,
pero aún puedes quedarte sin recursos si ejecutas un DIMM por canal, mezclas velocidades o configuras mal ajustes de energía en la BIOS.

Una cita sobre fiabilidad (idea parafraseada)

Werner Vogels (idea parafraseada): “Todo falla, todo el tiempo—diseña y opera como si esa fuera la norma.”

Tareas prácticas: comandos, salidas y decisiones (12+)

Estas son las tareas que realmente ejecuto cuando un host EPYC “debería ser más rápido” pero no lo es. Cada una incluye un fragmento de salida realista
y qué decisión tomas a partir de ello. Ejecútalas en el host, no en un contenedor, salvo que se indique lo contrario.

Tarea 1: Confirmar modelo de CPU, sockets y disposición de núcleos

cr0x@server:~$ lscpu
Architecture:                         x86_64
CPU op-mode(s):                       32-bit, 64-bit
CPU(s):                               128
Thread(s) per core:                   2
Core(s) per socket:                   64
Socket(s):                            1
NUMA node(s):                         4
Vendor ID:                            AuthenticAMD
Model name:                           AMD EPYC 9554 64-Core Processor
L3 cache:                             256 MiB
NUMA node0 CPU(s):                    0-31
NUMA node1 CPU(s):                    32-63
NUMA node2 CPU(s):                    64-95
NUMA node3 CPU(s):                    96-127

Qué significa: Tienes un socket pero cuatro nodos NUMA. Eso es una decisión de topología, no solo un dato.

Decisión: Si la carga es sensible a la latencia, planifica pinning y colocación de memoria conscientes de NUMA.
Si es de propósito general, deja NUMA visible pero evita pinning complejo a menos que midas una ganancia.

Tarea 2: Comprobar distancia NUMA (penalización local vs remota)

cr0x@server:~$ numactl --hardware
available: 4 nodes (0-3)
node 0 cpus: 0-31
node 0 size: 192000 MB
node 0 free: 121500 MB
node 1 cpus: 32-63
node 1 size: 192000 MB
node 1 free: 118200 MB
node 2 cpus: 64-95
node 2 size: 192000 MB
node 2 free: 119100 MB
node 3 cpus: 96-127
node 3 size: 192000 MB
node 3 free: 120900 MB
node distances:
node   0   1   2   3
  0:  10  12  12  12
  1:  12  10  12  12
  2:  12  12  10  12
  3:  12  12  12  10

Qué significa: El acceso a memoria remota cuesta más que el local (distancia 12 vs 10). No es catastrófico, pero es real.

Decisión: Para bases de datos y daemons de almacenamiento, alinea CPU/memoria a un nodo y procura mantener las interrupciones de E/S locales.

Tarea 3: Verificar velocidad y población de memoria

cr0x@server:~$ sudo dmidecode -t memory | egrep -i 'Locator:|Size:|Speed:|Configured Memory Speed:'
Locator: DIMM_A1
Size: 64 GB
Speed: 4800 MT/s
Configured Memory Speed: 4800 MT/s
Locator: DIMM_B1
Size: 64 GB
Speed: 4800 MT/s
Configured Memory Speed: 3600 MT/s

Qué significa: Un DIMM está bajando su frecuencia (configurado a 3600). Eso puede arrastrar todo el subsistema de memoria.

Decisión: Corrige las reglas de población (DIMMs emparejados, ranuras correctas). No hagas benchmarks hasta que la memoria funcione a la velocidad esperada.

Tarea 4: Comprobar comportamiento de frecuencia de CPU bajo carga

cr0x@server:~$ sudo turbostat --Summary --quiet --show Busy%,Bzy_MHz,IPC,IRQ,POLL --interval 1 --num_iterations 3
Busy%  Bzy_MHz  IPC   IRQ   POLL
38.45  2850     1.35  6200  0
92.10  2975     1.02  18900 0
91.88  2400     0.98  20100 0

Qué significa: La frecuencia cae a alto Busy% (política térmica/energética/firmware). El IPC también baja, lo que sugiere stalls de memoria o contención.

Decisión: Revisa el perfil de energía en BIOS, la refrigeración y el governor de Linux. Si importa el rendimiento, evita ajustes de energía conservadores.

Tarea 5: Inspeccionar driver/gobernador de frecuencia de CPU en Linux

cr0x@server:~$ cpupower frequency-info
analyzing CPU 0:
  driver: amd-pstate-epp
  CPUs which run at the same hardware frequency: 0
  available cpufreq governors: performance powersave
  current policy: frequency should be within 400 MHz and 3700 MHz.
                  The governor "powersave" may decide which speed to use
  current CPU frequency: 1580 MHz (asserted by call to hardware)

Qué significa: Estás en powersave. En un servidor que hace trabajo real, eso suele ser accidental.

Decisión: Para hosts críticos de rendimiento, establece performance y confirma que las térmicas son aceptables.

Tarea 6: Confirmar topología PCIe y anchos de enlace

cr0x@server:~$ lspci -tv
-[0000:00]-+-00.0  Advanced Micro Devices, Inc. [AMD] Device 14xx
           +-01.1-[01]----00.0  Samsung Electronics Co Ltd NVMe SSD Controller
           +-01.2-[02]----00.0  Samsung Electronics Co Ltd NVMe SSD Controller
           +-03.0-[03]----00.0  Mellanox Technologies MT28908 Family [ConnectX-6]
           \-04.0-[04]----00.0  Broadcom / LSI SAS3008 PCI-Express Fusion-MPT SAS-3

Qué significa: Los dispositivos están en diferentes root ports—buen indicio. Pero aún necesitas comprobar la velocidad/anchura negociada.

Decisión: Si un NVMe negoció x2 en vez de x4 (o Gen3 en vez de Gen4/5), corrige el cableado/backplane/bifurcación/BIOS antes de culpar al software.

Tarea 7: Validar velocidad/anchura PCIe negociada en un dispositivo

cr0x@server:~$ sudo lspci -s 01:00.0 -vv | egrep -i 'LnkCap:|LnkSta:'
LnkCap: Port #0, Speed 16GT/s, Width x4, ASPM L1, Exit Latency L1 <16us
LnkSta: Speed 8GT/s (downgraded), Width x4

Qué significa: Capaz de Gen4 (16GT/s) pero funcionando a Gen3 (8GT/s). Eso reduce el ancho de banda a la mitad.

Decisión: Revisa ajustes de PCIe en BIOS, backplane, retimers y firmware. No “optimices” el kernel para compensar una degradación física.

Tarea 8: Identificar distribución de colas e interrupciones NVMe

cr0x@server:~$ cat /proc/interrupts | egrep 'nvme|mlx5' | head
  95:   1200331   0   0   0   IR-PCI-MSI 524288-edge nvme0q0
  96:    903221   0   0   0   IR-PCI-MSI 524289-edge nvme0q1
  97:    910554   0   0   0   IR-PCI-MSI 524290-edge nvme0q2
 110:   3321100   0   0   0   IR-PCI-MSI 327680-edge mlx5_comp0

Qué significa: Todas las interrupciones cayendo en CPU0 (la primera columna) es un clásico destructor de rendimiento.

Decisión: Habilita/verifica irqbalance, o asigna afinidad de IRQs al nodo NUMA local del dispositivo. Esto suele ser una mejora de latencia “gratis”.

Tarea 9: Comprobar localidad de la NIC y asociación NUMA

cr0x@server:~$ for dev in /sys/class/net/enp*; do echo -n "$(basename $dev) "; cat $dev/device/numa_node; done
enp65s0f0 2
enp65s0f1 2

Qué significa: La NIC está conectada al nodo NUMA 2. Si tu carga corre en el nodo 0 con memoria en el nodo 0, estás pagando por la distancia.

Decisión: Para redes de alto throughput (Ceph, NVMe-oF, replicación), coloca los hilos de la pila de red cerca del nodo NUMA de la NIC.

Tarea 10: Detectar presión de ancho de banda de memoria vía contadores perf

cr0x@server:~$ sudo perf stat -a -e cycles,instructions,cache-misses,dTLB-load-misses -I 1000 -- sleep 3
#           time             counts unit events
     1.000233062     5,210,332,110      cycles
     1.000233062     3,101,229,884      instructions
     1.000233062        92,110,553      cache-misses
     1.000233062         1,020,112      dTLB-load-misses
     2.000472981     5,401,223,019      cycles
     2.000472981     3,002,118,991      instructions
     2.000472981       120,004,221      cache-misses
     2.000472981         1,230,888      dTLB-load-misses

Qué significa: Aumento de cache misses + caída de instrucciones por ciclo apunta a presión de memoria o mala localidad.

Decisión: Revisa la colocación NUMA, huge pages, comportamiento del allocator y la localidad de estructuras de datos antes de añadir más núcleos.

Tarea 11: Comprobar saturación y cola de I/O de disco

cr0x@server:~$ iostat -x 1 3
avg-cpu:  %user   %nice %system %iowait  %steal   %idle
          22.10    0.00    9.20    3.10    0.00   65.60

Device            r/s     w/s   rMB/s   wMB/s  avgrq-sz avgqu-sz await  svctm  %util
nvme0n1        1200.0  800.0   420.0   310.0     620.0     9.80  6.20  0.35  99.8

Qué significa: El dispositivo está ~100% util y la profundidad de cola es alta (avgqu-sz). Await es 6.2ms—alto para NVMe bajo esta carga.

Decisión: O el dispositivo está saturado (normal) o tienes un problema de interrupciones/NUMA que lo hace parecer saturado. Correlaciona con interrupciones y softirq de CPU.

Tarea 12: Verificar coste CPU de compresión/checksum del sistema de ficheros o ZFS (ejemplo: ZFS)

cr0x@server:~$ sudo zpool iostat -v 1 3
                              capacity     operations     bandwidth
pool                        alloc   free   read  write   read  write
tank                        12.1T  10.7T   9800   6200   1.1G   820M
  mirror-0                  12.1T  10.7T   9800   6200   1.1G   820M
    nvme-SAMSUNG_MZQLB1T9-0     -      -   4900   3100   560M   410M
    nvme-SAMSUNG_MZQLB1T9-1     -      -   4900   3100   560M   410M

Qué significa: Altas ops y ancho de banda; si el uso de CPU también es alto, las funciones de ZFS (compresión, checksums) pueden estar limitando por CPU, no por disco.

Decisión: Si la latencia es prioridad, reconsidera el nivel de compresión, recordsize y ajustes de sync—cuidadosamente y manteniendo la seguridad de los datos.

Tarea 13: Detectar sobrecarga de softirq (congestión de ruta de red/almacenamiento)

cr0x@server:~$ mpstat -P ALL 1 2 | head -n 20
Linux 6.5.0 (server)  01/10/2026  _x86_64_  (128 CPU)

01:01:10 PM  CPU   %usr  %nice  %sys %iowait  %irq  %soft  %steal  %idle
01:01:11 PM  all  18.20   0.00  12.30    2.10  0.90  15.40    0.00  51.10
01:01:11 PM    0   2.00   0.00   5.00    0.00  0.00  70.00    0.00  23.00

Qué significa: CPU0 está ahogado en softirq. Eso concuerda con “todas las interrupciones en CPU0”.

Decisión: Arregla la afinidad de IRQ. Si usas DPDK o busy polling, valida la configuración y asegúrate de que sea intencional.

Tarea 14: Verificar exposición de topología en virtualización (ejemplo KVM/QEMU)

cr0x@server:~$ virsh capabilities | egrep -n 'topology|numa|cells' | head
115:      <topology sockets='1' dies='1' clusters='1' cores='64' threads='2'/>
132:      <cells num='4'>
133:        <cell id='0'>

Qué significa: El host tiene 4 celdas NUMA. Tus VMs pueden configurarse para coincidir (o pueden quedar desajustadas).

Decisión: Para VMs grandes, expón NUMA al invitado y alinea vCPU/memoria. Para VMs pequeñas, mantenlo simple a menos que midas un beneficio.

Tarea 15: Comprobar evidencia de limitación térmica/energética

cr0x@server:~$ sudo journalctl -k --since "1 hour ago" | egrep -i 'thrott|powercap|edac|mce' | tail
Jan 10 12:35:22 server kernel: amd_pstate: limiting max performance due to platform profile
Jan 10 12:41:07 server kernel: EDAC amd64: ECC error detected on CPU#0 Channel:1 DIMM:0

Qué significa: El perfil de plataforma está limitando el rendimiento, y además tienes errores ECC. Ambos pueden manifestarse como “lentitud aleatoria”.

Decisión: Arregla las térmicas/perfil de energía primero; reemplaza o vuelve a asentar DIMMs problemáticos de inmediato. Afinar rendimiento sobre memoria inestable es autolesión.

Guion rápido de diagnóstico

Este es el flujo de “tengo 20 minutos antes de que la llamada de incidentes se convierta en teatro de improvisación”. Asume que tienes un host más lento de lo esperado
o que la latencia de cola está subiendo bajo carga.

Primero: separa “saturación de recursos” de “topología/patología”

  • Comprueba distribución de CPU y softirq: mpstat -P ALL 1 y cat /proc/interrupts. Si una CPU está al máximo en softirq, para. Arregla afinidad de IRQ.
  • Comprueba uso y cola de disco: iostat -x 1. Si %util ~100% con await alto, o estás realmente limitado por el dispositivo o tienes un problema de localidad/interrupciones que lo hace parecer así.
  • Comprueba presión de memoria: vmstat 1 (mira si/so), y contadores perf si están disponibles. Si estás intercambiando, todo lo demás es ruido de fondo.

Segundo: confirma la negociación física y la realidad del firmware

  • Degradaciones de enlace PCIe: lspci -vv para Speed/Width. Arregla problemas de Gen3 en hardware Gen4 antes de cambiar knobs del kernel.
  • Downclocking de memoria: dmidecode para encontrar DIMMs mal configurados. EPYC funcionará, pero tu ancho de banda se marchará discretamente.
  • Throttling por políticas de energía: cpupower frequency-info y logs. Muchas “regresiones misteriosas” son perfiles de energía.

Tercero: alinea la localidad en la ruta caliente

  • Mapeo de nodos NUMA: numactl --hardware, nodo NUMA de la NIC vía sysfs y localidad de dispositivos de almacenamiento.
  • Pin solo lo necesario: para VMs grandes o servicios dedicados, pinnea CPU y memoria. Para todo lo demás, empieza con arreglos de IRQ y energía.
  • Mide latencia de cola, no medias: los problemas de EPYC suelen esconderse en p99 mientras p50 está bien.

Broma #2: Si tu primer paso es “vamos a toquetear sysctl”, no estás diagnosticando—estás condimentando.

Tres mini-historias corporativas desde las trincheras

Mini-historia 1: El incidente causado por una suposición errónea

Un equipo de plataforma migró una flota de hosts intensivos en almacenamiento desde antiguos sistemas de doble socket a relucientes servidores mono-socket EPYC. El plan parecía infalible:
menos sockets, misma RAM, más núcleos, más NVMe. Esperaban menor latencia y menos consumo. La primera semana fue tranquila. Entonces el trabajo semanal pegó:
compactación de backups más indexación más tráfico de clientes. Las gráficas de latencia afilaron los dientes.

El on-call asumió “los discos están saturados.” El %util de NVMe era alto y las profundidades de cola parecían feas. Añadieron más discos al siguiente build
y distribuyeron los datos más amplio. Resultado: la misma latencia p99, ahora con más hardware.

El verdadero problema era la localidad. La NIC y la mitad del NVMe colgaban de una topología PCIe que el kernel estaba enviando interrupciones a CPU0.
CPU0 no estaba “ocupada” en espacio usuario; estaba ahogada en softirq y manejo de interrupciones. Los hilos de almacenamiento corrían en otro nodo NUMA,
cruzando constantemente límites de la interconexión para completar I/O. El sistema tenía núcleos de sobra—solo que no donde caía el trabajo.

La solución fue aburrida y quirúrgica: habilitar irqbalance como línea base y luego sobreescribir afinidades para la NIC y las colas NVMe para mantenerlas locales al nodo NUMA del dispositivo.
También ajustaron la colocación de VMs para que los daemons de almacenamiento y su memoria quedaran cerca de ese nodo.

La lección clave no fue “irqbalance es bueno.” Fue: la suposición errónea fue tratar la saturación NVMe como una propiedad del dispositivo en lugar de una propiedad de camino extremo a extremo.
En el mundo EPYC, la CPU y la tela NUMA son parte de tu subsistema de almacenamiento te guste o no.

Mini-historia 2: La optimización que salió mal

Un equipo de cómputo que ejecutaba un clúster de virtualización ocupado decidió pinnear todo. Su lógica era razonable: NUMA existe, por lo tanto pinnear es bueno,
por lo tanto pinnear todo es mejor. Pinnearon vCPUs, pinnearon memoria, pinnearon IRQs y pinnearon algunos hilos del kernel por si acaso.

El clúster se veía fantástico bajo cargas estables. Luego llegó la realidad: se evacuaron hosts para mantenimiento, migraron VMs y el orquestador
empezó a reordenar. De repente, algunos hosts tenían VMs “perfectamente pinneadas” sentadas en nodos NUMA equivocados porque las restricciones de colocación originales
no se preservaron durante las migraciones. El rendimiento se volvió inconsistente: algunas VMs iban genial, otras lentas, y la diferencia dependía de dónde aterrizaban.

El remezón fue operativo. La estrategia de pinning requería disciplina de colocación estricta, pero el equipo no tenía herramientas para validarla continuamente.
También crearon fragmentación: había núcleos libres, pero no con la forma NUMA correcta para ubicar nuevas VMs. El planificador empezó a rechazar colocaciones,
y la gente empezó a mover máquinas manualmente. Ahí aprendes cuán rápido un clúster se convierte en un artefacto hecho a medida.

Deshicieron la mayor parte. El pinning quedó para un pequeño conjunto de VMs de alto valor con ciclos de vida predecibles. Para todo lo demás, confiaron en valores por defecto sensatos:
huge pages cuando aplicaba, irqbalance con overrides dirigidos y una política a nivel host que evitara que la gestión de energía los sabotease.

La lección: una optimización que requiere operaciones perfectas no es una optimización; es un instrumento de deuda con interés variable.

Mini-historia 3: La práctica aburrida pero correcta que salvó el día

Una empresa desplegó nuevos hosts EPYC para un clúster de almacenamiento. Nada exótico: NVMe, NICs de alta velocidad, Linux estándar, monitorización estándar.
La ventana de cambio era corta, así que mantuvieron la imagen OS idéntica entre generaciones y confiaron en la automatización.

Un host empezó a mostrar picos de latencia intermitentes después de una semana. No lo suficiente para disparar alertas globales, pero sí para provocar reintentos de aplicaciones
y quejas de clientes. La gráfica parecía ruido aleatorio—cebo clásico de “es la red”.

La práctica que salvó fue dolorosamente aburrida: tenían una rutina que revisaba logs del kernel buscando errores de hardware corregidos como parte de la higiene semanal,
no solo durante incidentes. El operador detectó correcciones ECC y algunos mensajes PCIe AER en el host afectado. No hubo pánico, solo una dirección clara:
hardware o firmware, no ajuste de aplicación.

Programaron un mantenimiento controlado, reasentaron DIMMs, actualizaron firmware y reemplazaron el módulo sospechoso. Los picos desaparecieron.
Sin esa higiene, el equipo habría perdido semanas “afinando” afinidad de IRQ y parámetros de almacenamiento mientras la caja calladamente corroía la confianza.

La lección: el truco de rendimiento más rentable es prevenir que hardware defectuoso se haga pasar por un problema de software.

Errores comunes (síntomas → causa raíz → solución)

EPYC no crea errores nuevos. Hace más ruidosos los existentes. Aquí están los que veo repetidamente, con soluciones específicas.

1) Síntoma: picos de latencia p99 bajo carga; la CPU “parece ociosa” en general

  • Causa raíz: interrupciones/softirqs concentradas en pocas CPUs; la ruta caliente está ligada a CPU en espacio kernel.
  • Solución: revisa /proc/interrupts; habilita irqbalance; pinnea IRQs de NIC/NVMe a CPUs locales NUMA; verifica RPS/XPS si aplica.

2) Síntoma: rendimiento NVMe se estanca muy por debajo de lo esperado

  • Causa raíz: enlace PCIe negociado a menor velocidad (Gen3 vs Gen4/5) o menor ancho; retimers/backplane/BIOS en desacuerdo.
  • Solución: lspci -vv LnkSta; corrige ajustes BIOS; actualiza firmware; valida cableado/backplane; reintenta antes de afinar software.

3) Síntoma: la base de datos va más lenta tras una actualización a “más núcleos”

  • Causa raíz: saturación de ancho de banda de memoria, acceso remoto NUMA o pared de escalado por contención de locks.
  • Solución: alinea el proceso de BD CPU/memoria con el nodo NUMA; aumenta localidad; considera menos hilos; valida velocidad/población de memoria.

4) Síntoma: el cluster de virtualización tiene hosts “buenos” y “malos” al azar

  • Causa raíz: ajustes BIOS inconsistentes (modo NPS, perfil de energía), drivers/governors inconsistentes o drift en firmware.
  • Solución: estandariza BIOS/firmware; haz cumplir en el provisioning; audita con lscpu, cpupower e inventario DMI.

5) Síntoma: uso de CPU de almacenamiento explota tras activar compresión/cifrado

  • Causa raíz: la CPU se convierte en cuello de botella del almacenamiento; ancho de banda de memoria y comportamiento de caché dominan; la sobrecarga por núcleo escala mal.
  • Solución: mide con perf/turbostat; ajusta nivel de compresión; asegura distribución de IRQ; mueve daemons pesados a nodos locales; considera offload solo si es real.

6) Síntoma: “Pinneamos vCPUs y empeoró”

  • Causa raíz: pinning sin alinear localidad de memoria y E/S; o drift operativo hace que el pinning sea inconsistente tras migraciones.
  • Solución: pinnea como política completa (CPU + memoria + localidad de dispositivos) para un subconjunto pequeño; de lo contrario quita el pinning y arregla interrupciones/energía primero.

7) Síntoma: stalls frecuentes y pequeños, difíciles de reproducir

  • Causa raíz: errores ECC corregidos, reintentos PCIe AER o eventos de limitación térmica/energética.
  • Solución: inspecciona journalctl -k por EDAC/AER; atiende hardware; no “tunees alrededor” de advertencias de fiabilidad.

Listas de verificación / plan paso a paso

Paso a paso: incorporar un nuevo host EPYC a producción sin drama

  1. Estandariza ajustes de BIOS: perfil de energía, modo NPS, política SMT, ajustes de generación PCIe. Documenta la postura elegida y por qué.
  2. Valida población de memoria: ranuras correctas, DIMMs emparejados, velocidad configurada esperada. Corrige downclocking de inmediato.
  3. Verifica negociación PCIe: comprueba todos los NVMe y NICs para la velocidad/anchura esperada; asegura que no haya degradaciones silenciosas.
  4. Baselina comportamiento de frecuencia de CPU: confirma governor/driver; ejecuta una prueba corta de carga y verifica que las frecuencias no colapsen inesperadamente.
  5. Confirma forma NUMA: registra salidas de lscpu y numactl --hardware; almacénalas en el inventario del host.
  6. Establece política de interrupciones: habilita irqbalance como base, luego añade overrides de afinidad dirigidos para hotspots conocidos (NICs, NVMe) si tienes evidencia.
  7. Ejecuta una prueba rápida de almacenamiento: lecturas/escrituras aleatorias con profundidades de cola realistas; registra latencia p50/p95/p99, no solo throughput.
  8. Ejecuta una prueba rápida de red: valida velocidad de línea, coste de CPU y distribución de IRQ; asegura que ninguna CPU esté al máximo en softirq.
  9. Establece una vigilancia de “salud de hardware”: logs EDAC, MCE, AER monitorizados. Trata los errores corregidos como indicadores adelantados.
  10. Solo entonces afina knobs de carga: conteos de hilos, pinning, huge pages, ajustes de sistema de ficheros, etc.—basado en mediciones.

Lista de verificación: decidir entre EPYC mono-socket y dual-socket

  • Elige mono-socket si necesitas mucha E/S, memoria moderada y quieres licencias más simples y menor complejidad de dominios de fallo.
  • Elige dual-socket si realmente necesitas capacidad o ancho de banda de memoria más allá de lo que un socket ofrece, o tu carga demanda más endpoints PCIe sin switches.
  • Evita dual-socket “solo porque sí.” Duplica la complejidad NUMA y aumenta el radio de impacto por penalizaciones de memoria remota.

Lista de verificación: qué medir antes de culpar a EPYC

  • Velocidad/anchura negociada PCIe
  • Velocidad configurada de memoria y población de canales
  • Distribución de IRQs entre CPUs
  • Tiempo en softirq y hotspots por core
  • Colocación NUMA del proceso y su memoria
  • Gobernador de gestión de energía y evidencia de throttling
  • Latencia de cola (p99) bajo carga mixta

Preguntas frecuentes

1) ¿EPYC es “mejor” que Intel para servidores?

Depende de qué signifique “mejor”. EPYC ha sido especialmente fuerte cuando necesitas alta densidad de núcleos, muchas lanes PCIe y buen ancho de banda de memoria por dólar.
Pero “mejor” en producción también es madurez de firmware, estabilidad de la plataforma y cómo se comporta tu software con NUMA y alta paralelización.

2) ¿Por qué mi EPYC mono-socket muestra múltiples nodos NUMA?

Porque la plataforma puede configurarse con múltiples dominios NUMA por socket (modos NPS), y la topología chiplet/de E/S expone límites de localidad.
Trátalo como real: la latencia de memoria y la localidad de E/S pueden diferir por nodo incluso en un solo socket.

3) ¿Debo habilitar SMT (equivalente a hyperthreading) en EPYC?

Normalmente sí para cargas de throughput, entornos mixtos de VMs y servicios generales. Para escenarios estrictos de latencia o vecinos ruidosos, prueba ambas opciones.
SMT puede mejorar la utilización pero también aumentar la latencia de cola cuando la contención es alta.

4) ¿Por qué mi NVMe corre en Gen3 cuando soporta Gen4/Gen5?

Causas comunes: BIOS forzó la generación, limitaciones del backplane/retimer, dispositivos mixtos negociando a la baja, problemas de integridad de señal o firmware desactualizado.
Confirma con lspci -vv y arregla la capa física/firmware antes de afinar Linux.

5) ¿Necesito pinnear IRQs manualmente o irqbalance es suficiente?

Empieza con irqbalance. Si sigues viendo hotspots (una CPU al máximo en softirq) o necesitas latencia consistente, pinnea IRQs de NIC/NVMe
a CPUs locales del nodo NUMA del dispositivo. El pinning manual sin medición tiende a convertirse en folklore permanente.

6) ¿Cuál es la forma más rápida de saber si estoy limitado por ancho de banda de memoria?

Busca bajo IPC bajo carga (turbostat), aumento de cache misses (perf stat) y escalado que deja de mejorar con más hilos.
También verifica que la memoria no esté downclockeada y que los canales estén correctamente poblados.

7) ¿Un mayor conteo de núcleos siempre es mejor para nodos de almacenamiento?

No. Los nodos de almacenamiento pueden estar limitados por ancho de banda de memoria, manejo de interrupciones y eficiencia de la pila de red. Más núcleos ayudan solo si la ruta caliente
se paraleliza y se respeta la localidad. Si no, solo tendrás más núcleos mirando cómo uno hace el trabajo.

8) ¿Debo configurar más nodos NUMA por socket (NPS) para rendimiento?

A veces. Más nodos NUMA pueden mejorar la localidad si tu planificador y la colocación de la aplicación son NUMA-aware, especialmente para cargas I/O-intensivas.
Pero también aumenta la complejidad operativa. Si no tienes disciplina de colocación, menos nodos NUMA pueden ser más estables.

9) ¿Cuál es el peor hábito de “tuning” en EPYC?

Tratar la topología como opcional. Si ignoras distribución de IRQ, colocación de memoria y negociación PCIe, pasarás semanas “tuneando” sysctls y conteos de hilos
mientras el verdadero cuello de botella está a la vista.

Próximos pasos que no te avergonzarán

EPYC convirtió los servidores en una sala de exposición al volver a hacer importante la hoja de especificaciones: núcleos, lanes, canales y caché. Ese es el titular.
La realidad operativa es que la topología volvió a importar, y la topología castiga el pensamiento vago.

Pasos prácticos:

  1. Inventaría la topología en cada host: forma CPU/NUMA, nodos NUMA de NIC y NVMe, velocidades negociadas PCIe. Guárdalo en tu CMDB o metadatos de provisioning.
  2. Estandariza BIOS y políticas de energía en la flota. Perfiles inconsistentes crean “hosts encantados” que consumen tiempo SRE.
  3. Baselina IRQ y comportamiento de softirq bajo carga representativa. Si una CPU es el vertedero del kernel, arregla eso primero.
  4. Mide p99 antes y después de cambios. Si solo rastreas medias, declararás victoria mientras los usuarios siguen reintentando.
  5. Usa pinning con cirugía: resérvalo para cargas que lo merezcan y entornos que puedan mantenerlo.

La meta no es hacer que tus servidores EPYC sean impresionantes. Ya lo son. La meta es hacerlos aburridos—y mantenerlos aburridos cuando la carga se pone fea.

← Anterior
Copias de seguridad MySQL vs SQLite: ¿Cuál es más fácil de recuperar bajo presión?
Siguiente →
386: el momento en que la PC empezó a comportarse como servidor

Deja un comentario