10 mitos sobre las GPU que se niegan a morir

¿Te fue útil?

Si ejecutas cargas de trabajo de GPU en producción, ya te has topado con el mismo villano disfrazado de diez formas distintas: “La GPU va lenta.”
A veces es verdad. Más a menudo, la GPU está esperando: a tu CPU, a tu almacenamiento, a tu red, a tus controladores, al runtime del contenedor,
o a una sola bandera que convierte un acelerador de 20k$ en un calentador ambiental.

A continuación hay diez mitos sobre GPUs que siguen consumiendo presupuestos y sueño. Cada mito incluye una corrección práctica,
comandos que puedes ejecutar hoy y los tipos de modos de fallo que aparecen a las 2 a.m. cuando un entrenamiento “misteriosamente” empeora.

Guía de diagnóstico rápido: encuentre el cuello de botella en 10 minutos

La manera más rápida de depurar la “velocidad” de la GPU es dejar de hablar solo de GPUs y empezar a medir toda la canalización.
Buscas el primer recurso escaso. No el más caro.

1) Primera comprobación: ¿la GPU está realmente trabajando?

  • Mira la utilización de SM, la utilización de memoria y el consumo de energía. Si la energía es baja, probablemente no estés limitado por cómputo.
  • Comprueba los clocks y el throttling. Una GPU a 300 MHz no está “lenta”, está limitada.

2) Segunda comprobación: ¿el CPU/pipeline de datos la está dejando con hambre?

  • Uso alto de CPU, iowait elevado o lecturas lentas suelen significar que la GPU está esperando entrada.
  • Busca bloqueos del dataloader, tamaños de lote pequeños, aumentos excesivos en CPU o memoria host no pinneada.

3) Tercera comprobación: ¿estás limitado por ancho de banda (PCIe / red / almacenamiento)?

  • Un enlace PCIe con entrenamiento de enlace inferior (x16 → x4) o Gen4 → Gen3 limitará silenciosamente el throughput.
  • La red o el almacenamiento compartido pueden limitar el entrenamiento distribuido mucho antes de que “se acaben las GPUs”.

4) Cuarta comprobación: ¿luchas contra fricciones de software?

  • Desajustes de driver/runtime, runtime de contenedor incorrecto, modo persistente desactivado o variables de entorno mal puestas pueden forzar caminos lentos.
  • Las versiones del kernel, la configuración IOMMU y los cgroups también pueden introducir sobrecarga sorprendente.

5) Comprobación final: perfila una iteración de extremo a extremo

  • No adivines. Mide el tiempo por paso desglosado en entrada, transformaciones de CPU, transferencia H2D, cómputo GPU, D2H y sincronización.

Una idea parafraseada (lore de fiabilidad, atribuida): paraphrased ideaJohn Allspaw (operaciones y respuesta a incidentes): el comportamiento del sistema tiene sentido una vez que ves las restricciones.
En el mundo GPU, las restricciones casi nunca están donde te gustaría que estuvieran.

Los 10 mitos (y qué hacer en su lugar)

Mito 1: “La utilización de GPU debe ser ~100% o estás desperdiciando dinero.”

“Utilización” es una de esas métricas que suena objetiva y se comporta como chisme. Una GPU puede mostrar 20–40% de utilización
y aún estar perfectamente sana si tu modelo tiene puntos frecuentes de sincronización, kernels cortos o está limitada por latencia.
A la inversa, puedes alcanzar 99% de utilización haciendo el trabajo equivocado—como reformatear tensores constantemente o quemar ciclos en casts innecesarios.

Qué hacer en su lugar:

  • Monitorea el tiempo por paso y el throughput (ej.: muestras/seg) como KPIs principales.
  • Observa el consumo de energía y los clocks. El trabajo intensivo en cómputo suele consumir energía.
  • Busca espera de CPU y bloqueos del dataloader antes de perseguir “más utilización”.

Decisión práctica: si el tiempo por paso es estable y cumple los SLOs, no “arregles” la utilización. Si el tiempo por paso empeora, encuentra el bloqueo.

Mito 2: “Más VRAM hace que el entrenamiento sea más rápido.”

La VRAM es capacidad, no potencia. Más VRAM te permite ajustar lotes más grandes, modelos mayores, secuencias más largas o más activaciones en caché.
No incrementa automáticamente FLOPS ni ancho de banda de memoria. A veces más VRAM tienta a los equipos a usar lotes más grandes que reducen la generalización o desestabilizan el entrenamiento, lo que es una regresión de rendimiento con pasos extra.

Qué hacer en su lugar:

  • Compra VRAM para ajuste (¿puede ejecutarse?) y para reducir recomputación (elecciones de checkpointing de activaciones), no por velocidad per se.
  • Haz benchmarks con tamaño de lote fijo primero. Luego explora escalar el tamaño de lote y la tasa de aprendizaje correctamente.

Hecho histórico: Las GPUs de la era temprana de CUDA a menudo tenían mucha menos memoria que las CPUs, lo que obligó a la industria a inventar batching más inteligente,
kernels fusionados y precisión mixta para trabajar dentro de presupuestos de VRAM ajustados.

Mito 3: “Si cabe en VRAM, estás a salvo de errores out-of-memory.”

La frase “cabe en VRAM” oculta dos trampas: la fragmentación y el uso pico.
Muchos frameworks asignan y liberan buffers temporales durante las pasadas forward/backward. Los picos pueden superar la huella en estado estable.
La fragmentación puede impedir asignar un bloque contiguo grande incluso cuando la “memoria libre” parece amplia.

Qué hacer en su lugar:

  • Mide la memoria pico por iteración. Observa crecimiento con el tiempo (fugas, cachés, acumulación de grafo).
  • Usa controles del allocador (donde esté soportado) y evita patrones patológicos de asignación (muchos tensores de tamaños variables).
  • Prefiere formas y tamaños de lote consistentes; las formas dinámicas son magníficas hasta que estresan el allocador.

Dato interesante: los allocadores de memoria GPU frecuentemente usan estrategias de caché para evitar asignaciones costosas en dispositivo; “reservado” no es “fuga”.

Mito 4: “PCIe no importa—el cómputo es el cuello de botella.”

PCIe importa cada vez que mueves datos host↔device o device↔device sin una interconexión más rápida. Lotes pequeños, transferencias frecuentes
o preprocesado intensivo en CPU pueden convertir a PCIe en el metrónomo de tu trabajo. Peor aún, PCIe suele fallar silenciosamente:
un slot que funcione a x4 o un enlace entrenado en Gen3 en lugar de Gen4 puede parecer “bien” pero rendir como un coche de alquiler con el freno de mano puesto.

Qué hacer en su lugar:

  • Mantén los datos en la GPU por más tiempo. Fusiona operaciones. Evita enviar tensores al CPU por conveniencia.
  • Valida ancho y velocidad del enlace. No lo asumas.
  • Usa memoria pinneada y copias asíncronas cuando debas transferir.

Hecho histórico: NVLink se introdujo en parte porque el ancho de banda de PCIe no seguía el ritmo del entrenamiento multi-GPU y el paralelismo de modelos.

Mito 5: “Los Tensor Cores / la precisión mixta siempre son más rápidos.”

La precisión mixta puede ser una bendición. También puede ser una factura. Obtienes mejoras cuando tu mezcla de modelo y kernels
está configurada para usar caminos de cálculo rápidos y cuando la sobrecarga (casts, loss scaling, sincronización) no domina.
Algunos modelos se vuelven limitados por memoria o sufren overhead de lanzamiento de kernel, donde la reducción de precisión no ayuda mucho.

Qué hacer en su lugar:

  • Haz benchmarks FP32 vs AMP con semillas fijas y dataloading idéntico.
  • Vigila la inestabilidad numérica: NaNs, picos de loss, gradientes divergentes.
  • Confirma que el camino de cálculo rápido se esté usando realmente (profiling), no solo solicitado.

Dato interesante: la “era de Tensor Core” comenzó con NVIDIA Volta (V100), y cambió cómo los frameworks ML programan GEMMs y convoluciones.

Mito 6: “Si nvidia-smi muestra memoria usada, la GPU está trabajando.”

El uso de VRAM no es actividad. Puede significar simplemente que el proceso inicializó un contexto y cachéó asignaciones.
Puedes dejar 30 GB de tensores en una GPU y hacer exactamente cero cómputo útil si tu trabajo está atascado en el preprocesado en CPU,
bloqueado en un lock o en un punto muerto (deadlock) en el rendezvous distribuido.

Qué hacer en su lugar:

  • Comprueba la utilización de SM, el consumo de energía y la utilización por proceso.
  • Correlaciona con los logs de la aplicación: ¿aumenta el contador de iteración? ¿Estás atascado antes del primer paso?

Broma #1: Una GPU con VRAM llena y sin cómputo es como una sala de reuniones “reservada” todo el día porque alguien dejó una botella de agua dentro.

Mito 7: “El escalado multi-GPU es básicamente lineal.”

El escalado lineal es una demo de marketing donde la red nunca pierde un paquete, los tamaños de lote escalan perfectamente y nadie registra nada en INFO.
En sistemas reales, el overhead de all-reduce, los stragglers, la contención del pipeline de entrada y las restricciones de topología de NCCL zampan tus ganancias.

Qué hacer en su lugar:

  • Mide la eficiencia de escalado (throughput / número de GPUs) y observa cuándo cae.
  • Valida la topología: PCIe, NVLink, colocación NUMA y afinidad de NIC.
  • Arregla los stragglers primero: un worker lento puede arrastrar todo el trabajo.

Dato interesante: ring all-reduce hizo práctico el entrenamiento distribuido porque evita un cuello de botella de servidor de parámetros único, pero aún es sensible al enlace más lento.

Mito 8: “Los problemas de rendimiento de GPU se resuelven con ‘actualizar el driver’.”

Los drivers importan. Pero “actualiza el driver” es el equivalente operacional de “prueba a apagar y encender”.
A veces es correcto; a menudo distrae del verdadero cuello de botella—bloqueos de datos, clocks incorrectos, límites de potencia,
o un runtime de contenedor que ni siquiera expone la GPU correctamente.

Qué hacer en su lugar:

  • Fija combinaciones driver/toolkit conocidas y buenas para tu flota. Actualiza intencionalmente, no emocionalmente.
  • Cuando actualices, valida con una pequeña batería de pruebas de rendimiento y corrección.

Hecho histórico: la separación driver/runtime de CUDA es poderosa pero implacable; la brecha de “funciona en mi portátil” a menudo se esconde en la compatibilidad de versiones.

Mito 9: “Las térmicas solo importan para gamers.”

En producción, las térmicas son finanzas. Una GPU que reduzca su frecuencia por limitación de potencia o térmica
bajará de reloj, convirtiendo tu trabajo cuidadosamente ajustado en un goteo lento. Los centros de datos están llenos de causas para esto: filtros obstruidos,
ventiladores fallidos, flujo de aire extraño en un chasis o alguien instalando hardware de alto TDP junto a ese servidor que ya corre caliente.

Qué hacer en su lugar:

  • Monitorea temperaturas, potencia y razones de throttling.
  • Valida que tu límite de potencia esté correctamente configurado y que la refrigeración haga realmente lo que crees.

Dato interesante: muchas GPUs prefieren el throttling por límite de potencia antes que apagarse por sobrecalentamiento; puedes perder rendimiento sin ver un evento drástico de “sobrecalentamiento”.

Mito 10: “Las GPUs son lo difícil; el almacenamiento ya está resuelto.”

El almacenamiento es donde el “entrenamiento rápido” va a morir en silencio. Si tu dataset vive en un sistema de archivos compartido muy ocupado,
o haces lecturas aleatorias de muchos archivos pequeños, tu GPU pasará la vida esperando el siguiente lote.
Culparás a CUDA, luego a los drivers, luego a la fase lunar, y todo el tiempo es una tormenta de metadatos en el NAS.

Qué hacer en su lugar:

  • Mide el throughput del pipeline de entrada y la latencia de almacenamiento durante el entrenamiento.
  • Usa sharding, formatos de registros más grandes, caches NVMe locales y menos archivos pequeños.
  • Prefiere lecturas algo secuenciales y prefetching sobre “acceso aleatorio YOLO”.

Broma #2: La GPU es un coche de carreras; alimentarla desde un NFS compartido lleno de JPEGs pequeños es como remolcar un barco con una bicicleta.

Hecho histórico: el auge de formatos tipo TFRecord/WebDataset fue impulsado tanto por la escalabilidad de metadatos y almacenamiento como por la conveniencia en ML.

Breves datos históricos y de contexto (porque los mitos tienen historias de origen)

  • CUDA se lanzó en 2007, convirtiendo las GPUs de dispositivos solo para gráficos a hardware de cómputo paralelo de propósito general.
  • Los Tensor Cores llegaron con Volta (2017), desplazando el ajuste de rendimiento hacia math de matrices y elecciones de precisión.
  • El “modo persistente” existe porque inicializar contextos GPU repetidamente puede añadir segundos de sobrecarga—doloroso en planificadores por lotes.
  • Multi-Instance GPU (MIG) de NVIDIA hizo las GPUs seccionables para aislamiento, pero también generó preguntas semanales de “¿por qué mi GPU es pequeña?”.
  • NCCL se convirtió en la librería por defecto de comunicación colectiva porque el entrenamiento distribuido necesita colectivas eficientes en ancho de banda.
  • Los problemas de entrenamiento de enlace PCIe son más antiguos que el ML moderno; el problema simplemente se hizo caro cuando el dispositivo pasó a ser una GPU.
  • En Linux, la memoria host pinneada (page-locked) es la diferencia entre transferencias asíncronas y “¿por qué memcpy bloquea mi paso?”.
  • Los clocks de GPU pueden regirse por topes de potencia, térmicas y clocks de aplicación—tres perillas distintas que la gente confunde constantemente.

Tareas prácticas: comandos, salidas y decisiones

Estas son cosas reales que puedes ejecutar en un host GPU Linux. Cada tarea incluye qué significa la salida y qué decisión tomar a partir de ella.
No las trates como una lista para ejecutar una vez; trátalas como instrumentos que mantienes calibrados.

Task 1: Confirmar que la GPU es visible y el driver está sano

cr0x@server:~$ nvidia-smi
Tue Jan 21 11:02:13 2026
+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 550.54.14              Driver Version: 550.54.14      CUDA Version: 12.4   |
|-----------------------------------------+----------------------+----------------------|
| GPU  Name                 Persistence-M | Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |         Memory-Usage | GPU-Util  Compute M. |
|                                         |                      |               MIG M. |
|=========================================+======================+======================|
|   0  NVIDIA A100-SXM4-40GB          On  | 00000000:81:00.0 Off |                    0 |
| 34%   52C    P0              180W / 400W|  12000MiB / 40536MiB |     62%      Default |
+-----------------------------------------+----------------------+----------------------+
| Processes:                                                                              |
|  GPU   GI   CI        PID   Type   Process name                              GPU Memory |
|        ID   ID                                                               Usage      |
|=======================================================================================|
|    0   N/A  N/A     23141      C   python                                        11850MiB |
+---------------------------------------------------------------------------------------+

Significado: el driver se carga, la GPU está presente y un proceso la está usando.
Decisión: si esto falla o muestra “No devices were found”, detente y arregla drivers/runtime del contenedor/PCIe antes de perseguir rendimiento.

Task 2: Vigilar utilización, clocks y potencia en el tiempo (detecta inanición vs throttling)

cr0x@server:~$ nvidia-smi dmon -s pucmt
# gpu   pwr gtemp mtemp sm   mem   enc   dec   mclk  pclk
# Idx     W     C     C   %     %     %     %   MHz   MHz
    0   185    53     -  61    48     0     0  1215  1410
    0    85    50     -   8     6     0     0  1215   510
    0   190    54     -  63    49     0     0  1215  1410

Significado: cuando SM% y la potencia caen juntos, la GPU está inactiva o esperando. Cuando SM% es alto pero los clocks son bajos, puede que estés en throttling.
Decisión: inactividad → investiga pipeline de entrada/CPU/IO; throttling → revisa térmicas, límites de potencia y clocks.

Task 3: Comprobar razones de throttling (límites de potencia/térmicos)

cr0x@server:~$ nvidia-smi -q -d PERFORMANCE | sed -n '1,160p'
==============NVSMI LOG==============

Performance
    Clocks Throttle Reasons
        Idle                        : Not Active
        Applications Clocks Setting  : Not Active
        SW Power Cap                : Active
        HW Slowdown                 : Not Active
        HW Thermal Slowdown         : Not Active
        Sync Boost                  : Not Active

Significado: “SW Power Cap: Active” indica que la GPU está siendo limitada por un tope de potencia.
Decisión: confirma que los topes de potencia sean intencionales; si no lo son, ajusta el límite de potencia o arregla políticas de rack/energía/refrigeración.

Task 4: Confirmar velocidad y ancho del enlace PCIe (asesino silencioso de rendimiento)

cr0x@server:~$ nvidia-smi -q | grep -A3 "PCI"
    PCI
        Bus                          : 0x81
        Device                       : 0x00
        Domain                       : 0x0000
--
        Link Width                   : 16x
        Link Generation              : 4

Significado: x16 Gen4 es lo que quieres en servidores modernos; x8 o Gen3 puede esperarse en algunas plataformas pero debe conocerse.
Decisión: si ves x4 o Gen1/2/3 inesperadamente, reubica la tarjeta, revisa la BIOS, revisa risers y valida el cableado del slot.

Task 5: Comprobar topología NUMA y afinidad del dispositivo (evita dolor cross-socket)

cr0x@server:~$ nvidia-smi topo -m
        GPU0    NIC0    CPU Affinity    NUMA Affinity
GPU0     X      PHB     0-31            0
NIC0    PHB      X      0-31            0

Significado: GPU y NIC comparten un host bridge PCIe (PHB) y están cercanos al mismo nodo NUMA.
Decisión: si la GPU está en el nodo NUMA 1 y tus threads del dataloader corren en el nodo 0, fija procesos/IRQs para reducir latencia.

Task 6: Validar acceso a la GPU desde el contenedor (el clásico “está ejecutándose en CPU”)

cr0x@server:~$ docker run --rm --gpus all nvidia/cuda:12.4.1-base-ubuntu22.04 nvidia-smi
Tue Jan 21 11:03:48 2026
+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 550.54.14              Driver Version: 550.54.14      CUDA Version: 12.4   |
+---------------------------------------------------------------------------------------+

Significado: el contenedor puede ver la GPU a través del runtime.
Decisión: si esto falla, arregla la configuración de NVIDIA Container Toolkit/runtime antes de culpar a tu código ML.

Task 7: Confirmar que los módulos del kernel del driver correctos están cargados

cr0x@server:~$ lsmod | grep -E '^nvidia|^nvidia_uvm'
nvidia_uvm           1679360  0
nvidia_drm            126976  2
nvidia_modeset       1327104  1 nvidia_drm
nvidia              62287872  72 nvidia_uvm,nvidia_modeset

Significado: la ausencia de nvidia_uvm puede romper algunas cargas CUDA; la ausencia de módulos core significa que el driver no está cargado.
Decisión: si faltan módulos, inspecciona secure boot, construcción DKMS, actualización de kernel e integridad de la instalación del driver.

Task 8: Detectar cuellos de botella en CPU (iowait y cambios de contexto)

cr0x@server:~$ mpstat -P ALL 1 3
Linux 6.5.0-21-generic (train-node-07)  01/21/2026  _x86_64_  (64 CPU)

11:04:10 AM  CPU   %usr %nice %sys %iowait %irq %soft %steal %idle
11:04:11 AM  all   420.0 0.0  35.0   98.0  0.0  2.0   0.0  3445.0
11:04:12 AM  all   415.0 0.0  33.0  105.0  0.0  2.0   0.0  3445.0

Significado: iowait significativo sugiere que la latencia de almacenamiento está limitando tu pipeline; sys alto puede indicar sobrecarga de red o sistema de archivos.
Decisión: si iowait es alto mientras la GPU está inactiva, prioriza arreglos de almacenamiento y formato de entrada sobre ajuste de GPU.

Task 9: Comprobar latencia y throughput del sistema de archivos en la ruta del dataset

cr0x@server:~$ iostat -xz 1 3
Linux 6.5.0-21-generic (train-node-07)  01/21/2026  _x86_64_  (64 CPU)

Device            r/s   rkB/s  rrqm/s  %rrqm r_await aqu-sz  %util
nvme0n1         820.0 52480.0    12.0   1.4    1.2   0.9    58.0
nfs0           1200.0 19200.0     0.0   0.0   18.5  22.0    99.0

Significado: el dispositivo tipo NFS muestra await alto y 99% de utilización: estás limitado por lectura de almacenamiento.
Decisión: stagea datos a NVMe local, shardea/empaca archivos, añade cache o mueve a un formato con menos operaciones de metadatos.

Task 10: Demostrar que no estás intercambiando (swapping) ni con presión de memoria en el host

cr0x@server:~$ free -h
               total        used        free      shared  buff/cache   available
Mem:           503Gi       212Gi        21Gi       2.1Gi       270Gi       286Gi
Swap:           16Gi       7.5Gi       8.5Gi

Significado: uso de swap durante el entrenamiento es una bandera roja; puede bloquear dataloaders, tokenizadores y capas de caché.
Decisión: reduce huella de memoria en host, aumenta RAM o limita el paralelismo; evita swap en nodos de entrenamiento críticos para rendimiento.

Task 11: Confirmar que el proceso realmente está usando la GPU (y no está atascado)

cr0x@server:~$ ps -o pid,ppid,stat,etime,cmd -p 23141
  PID  PPID STAT     ELAPSED CMD
23141 22980 Sl+      00:17:42 python train.py --config prod.yaml

Significado: el proceso está vivo; “Sl+” indica que duerme con threads—podría ser normal o estar esperando.
Decisión: si la GPU está inactiva y el proceso duerme, inspecciona el dataloader, locks o barreras distribuidas.

Task 12: Inspeccionar uso por proceso de GPU y modo de cómputo

cr0x@server:~$ nvidia-smi pmon -c 1
# gpu        pid  type    sm   mem   enc   dec   jpg   ofa   command
    0      23141     C    62    48     0     0     0     0   python
    0      1822      G     0     1     0     0     0     0   Xorg

Significado: python consume SM y memoria. Si SM es 0 mientras la memoria es alta, probablemente estás atascado o entre pasos.
Decisión: correlaciona con logs de la app; si está bloqueado, adjunta un profiler o habilita logging de depuración alrededor de la obtención de datos y la pasada forward.

Task 13: Comprobar ECC de GPU y contadores de error (corrupción silenciosa y reintentos)

cr0x@server:~$ nvidia-smi -q -d ECC | sed -n '1,120p'
ECC Mode
    Current ECC                    : Enabled
    Pending ECC                    : Enabled

ECC Errors
    Volatile
        Single Bit
            Device Memory          : 0
        Double Bit
            Device Memory          : 0

Significado: ECC está activado y los contadores están limpios.
Decisión: si ves errores corregibles en aumento, planifica mantenimiento; si aparecen errores no corregibles, drena el nodo.

Task 14: Validar modo persistente de GPU (reducir overhead de init y flakiness)

cr0x@server:~$ nvidia-smi -pm 1
Enabled persistence mode for GPU 00000000:81:00.0.

Significado: el modo persistente mantiene el contexto del driver caliente.
Decisión: actívalo en nodos de cómputo dedicados a menos que tu modelo operativo requiera otra cosa (ej.: ahorro de energía estricto).

Task 15: Confirmar política de clocks / clocks de aplicación (evitar downclock accidental)

cr0x@server:~$ nvidia-smi -q -d CLOCK | sed -n '1,140p'
Clocks
    Graphics                        : 1410 MHz
    SM                              : 1410 MHz
    Memory                          : 1215 MHz

Applications Clocks
    Graphics                        : 1410 MHz
    Memory                          : 1215 MHz

Significado: los clocks están donde esperas. Si los clocks de aplicación están bajos, tendrás bajo rendimiento “misteriosamente”.
Decisión: estandariza configuraciones de clocks vía provisión y audita desviaciones tras actualizaciones de driver.

Tres micro-historias del mundo corporativo

Micro-historia 1: El incidente causado por una suposición equivocada (fallo de GPU que en realidad era almacenamiento)

Una empresa mediana ejecutaba re-entrenamientos nocturnos en un clúster compartido. Una semana, el tiempo de entrenamiento se duplicó. El on-call vio baja utilización de GPU,
lo clasificó como “degradación de GPU” y escaló a hardware. Se abrió un ticket con el proveedor. Se discutieron plazos de reemplazo.
El CFO se interesó brevemente por machine learning, que es señal de que fue grave.

La primera pista fue que las GPUs no estaban calientes. El consumo de energía era bajo y entrecortado, como un trabajo que corre a sprints y luego duerme.
Mientras tanto, el iowait de CPU subió y el sistema de archivos compartido parecía haber pillado la gripe: latencia alta, carga alta de metadatos.
El modelo estaba bien; las GPUs estaban bien. El pipeline del dataset estaba roto silenciosamente.

La “optimización” que lo desencadenó fue inocente: una actualización del dataset que aumentó el número de archivos pequeños al dividir shards “para paralelismo”.
Mejoró un benchmark en el portátil de un desarrollador con SSD local, luego explotó en producción sobre almacenamiento compartido.
El job de entrenamiento comenzó a hacer decenas de miles de opens y stats por minuto a través de muchos workers.

Arreglarlo fue aburrido: empacar muestras en shards más grandes, stagear a NVMe local y prefetch. La utilización de GPU subió como efecto secundario,
pero la verdadera ganancia fue tiempo por paso predecible. El ticket de hardware se cerró con la humilde vergüenza que merecía.

Micro-historia 2: La optimización que salió mal (precisión mixta en todas partes, corrección en ninguna)

Otra organización persiguió la velocidad de entrenamiento. Activaron precisión mixta automática globalmente y celebraron un gran aumento de throughput en un nodo.
Luego el entrenamiento distribuido empezó a producir NaNs intermitentes. No siempre. Lo suficiente como para arruinar la confianza y disparar reruns.
El patrón del incidente fue clásico: “Funciona en staging, falla en producción, solo cuando la luna está… ocupada.”

El problema real no era AMP en sí. Era una capa del modelo que era numéricamente delicada bajo precisión reducida,
más una configuración de loss scaling que era adecuada para una distribución de dataset y frágil para otra.
Añade ordenamientos distintos del dataloader multi-worker y la inestabilidad afloró.

El equipo respondió deshabilitando AMP por completo. El entrenamiento se estabilizó, pero el throughput quedó por debajo del objetivo de negocio.
Luego intentaron compensar aumentando el tamaño de lote. Eso cambió la convergencia, requirió retuning de tasa de aprendizaje y causó una segunda ola de regresiones:
modelos entrenados más rápido pero con peor desempeño.

La solución eventual fue disciplinada: mantener selectivamente operaciones sensibles en FP32, validar el loss scaling, añadir guardias NaN
y controlar cambios con una pequeña suite de corrección. AMP volvió—esta vez como decisión de ingeniería, no como un interruptor global.
La lección no fue “AMP es arriesgado”. La lección fue “trata los cambios de rendimiento como cambios de producción: observa, prueba y despliega con cuidado.”

Micro-historia 3: La práctica tediosa pero correcta que salvó el día (topología y pinning)

Una empresa ejecutaba inferencia multi-GPU con SLOs estrictos de latencia tail. Un día, la latencia p95 subió sin un cambio claro en el código.
El servicio parecía sano: sin errores, GPUs visibles, sin alarmas térmicas obvias. Pero la latencia se desplazó hacia arriba como una fuga lenta.

Tenían una práctica aburrida que rindió frutos: cada arranque de nodo ejecutaba un pequeño script de “sanidad de hardware”.
Capturaba ancho de enlace PCIe, afinidad NUMA, clocks GPU, versiones de driver y métricas básicas de almacenamiento, y luego las comparaba con una línea base conocida.
Cuando p95 cambió, no adivinaron; hicieron un diff.

El diff mostró que un nodo tenía la GPU en un nodo NUMA distinto al de la NIC tras un reemplazo de placa base.
La carga hacía transferencias frecuentes host↔device para pre/post-procesado.
El tráfico cross-socket aumentó latencia y jitter. La GPU no estaba más lenta; el camino de memoria era más largo.

La solución fue simple: fijar el proceso y las asignaciones de memoria al NUMA correcto, ajustar la afinidad de IRQ
y actualizar la documentación del rack para que futuros reemplazos respeten la topología del slot. Sin heroicidades, sin reescrituras.
Solo la negativa a “asumir que el bus está bien”.

Errores comunes: síntoma → causa raíz → solución

1) Síntoma: la memoria GPU está alta, la utilización de GPU cerca de cero

  • Causa raíz: bloqueo del pipeline de datos (latencia de almacenamiento, deadlock del dataloader, transformaciones de CPU demasiado lentas), o el job está atascado antes de la primera iteración.
  • Solución: mide el desglose del tiempo por paso; revisa iowait; reduce lecturas de archivos pequeños; habilita prefetch; incrementa workers del dataloader con cuidado; usa memoria pinneada.

2) Síntoma: una GPU más nueva es más lenta que la antigua

  • Causa raíz: tope de potencia, clocks equivocados, entrenamiento de enlace PCIe o un modelo limitado por memoria y no por cómputo.
  • Solución: comprueba razones de throttling y enlace PCIe; compara consumo de potencia; perfila kernels; ajusta tamaño de lote y fusión en lugar de culpar al silicio.

3) Síntoma: OOMs aleatorios de CUDA aunque “hay memoria libre”

  • Causa raíz: fragmentación o picos de memoria (formas diferentes, longitudes de secuencia variables, grafos dinámicos), o fuga de memoria en capas de caché.
  • Solución: usa formas fijas cuando sea posible; limita la longitud máxima de secuencia; reduce el lote; limpia cachés en puntos seguros; reinicia workers para resetear fragmentación cuando sea necesario.

4) Síntoma: el escalado multi-GPU es terrible, siempre hay una GPU atrasada

  • Causa raíz: worker straggler (contención de CPU, nodo NUMA distinto, IO de vecino ruidoso), o NCCL usando una interfaz/topología subóptima.
  • Solución: valida la topología; fija threads de CPU; asegura localidad de almacenamiento consistente; configura NCCL para la NIC correcta; elimina sesgos por rango en el dataloading.

5) Síntoma: el entrenamiento va rápido un tiempo y luego se va ralentizando gradualmente

  • Causa raíz: contención de almacenamiento en background, throttling térmico de CPU, presión de memoria causando swap, o una tormenta de métricas/logging que crece con el tiempo.
  • Solución: monitorea en el tiempo; limita logging; aísla IO de entrenamiento; revisa térmicas del host; verifica que no haya crecimiento/fugas de memoria.

6) Síntoma: “GPU disponible” pero el código corre en CPU

  • Causa raíz: contenedor no usa runtime GPU, build incorrecto (solo CPU), variables de visibilidad de dispositivo faltantes, o el framework no mueve tensores al dispositivo.
  • Solución: valida docker run --gpus all nvidia-smi; comprueba el placement de dispositivos en el framework; aplica aserciones de dispositivo en código y CI.

7) Síntoma: alta utilización de GPU pero bajo throughput

  • Causa raíz: estás haciendo trabajo caro de forma ineficiente: kernels diminutos, sincronización excesiva, tamaño de lote pobre o operaciones no fusionadas.
  • Solución: perfila; aumenta el lote; fusiona ops; reduce puntos de sincronización; evita viajes frecuentes al CPU.

Listas de verificación / plan paso a paso

Paso a paso: desde un reporte de “GPU lenta” hasta la causa raíz

  1. Captura una línea base. Registra tiempo por paso, throughput y identificadores de hardware para una ejecución. Si no puedes comparar, no puedes depurar.
  2. Revisa la salud de la GPU. Ejecuta nvidia-smi, revisa errores/ECC, revisa clocks y potencia.
  3. Revisa la utilización con contexto. Usa nvidia-smi dmon mientras el job está activo; correlaciona caídas con logs del dataloader.
  4. Valida la topología. Confirma ancho/versión PCIe y afinidad NUMA. Arregla colocaciones obvias primero.
  5. Inspecciona la presión del host. iowait de CPU, uso de swap, presión de memoria y latencia del sistema de archivos durante el job.
  6. Demuestra el throughput del pipeline de datos. Mide tasas de lectura y latencia en la ruta del dataset; confirma conteo de archivos y patrón de acceso.
  7. Perfila una iteración. Identifica tiempo en entrada vs H2D vs cómputo GPU vs sincronización.
  8. Cambia una variable a la vez. Tamaño de lote, num_workers, profundidad de prefetch, modo de precisión. Mide tras cada cambio.
  9. Despliega de forma segura. Controla cambios con una pequeña suite de rendimiento+corrección; evita toggles a toda la flota sin canarios.

Checklist: “Vamos a comprar GPUs”

  • Decidan si son limitados por cómputo o por memoria/anchura de banda mediante profiling, no intuiciones.
  • Presupuesta para almacenamiento y red. Tus GPUs solo son tan rápidas como tu entrada y tu all-reduce.
  • Valida potencia y refrigeración para cargas sostenidas, no para demos de pico.
  • Estandariza una matriz de driver/toolkit conocida y buena e insértala en la provisión.

Checklist: “Vamos a ejecutar multi-GPU / distribuido”

  • Confirma topología NCCL y afinidad de NIC.
  • Elimina stragglers: dataloading consistente, pinning de CPU consistente, IO consistente.
  • Mide eficiencia de escalado en 1, 2, 4, 8… GPUs. Detente cuando las ganancias se aplanen y arregla la restricción.

Preguntas frecuentes

1) ¿Por qué mi utilización de GPU es baja aunque el entrenamiento sea lento?

Utilización baja más entrenamiento lento suele significar que la GPU está esperando: dataloading, latencia de almacenamiento, transformaciones de CPU o sincronización.
Revisa consumo de energía y clocks; luego revisa iowait y latencia de lectura del dataset.

2) ¿Es 100% de utilización de GPU un buen objetivo para servicios de inferencia?

No si te importa la latencia. Para inferencia online, mantener la GPU “caliente” suele aumentar la latencia tail y te vuelve frágil ante picos de tráfico.
Prioriza SLOs (p95/p99) y planificación de capacidad, no trofeos de utilización.

3) ¿Cómo sé si estoy limitado por cómputo o por memoria?

Una pista rápida: alta utilización de SM y alto consumo de energía sugiere presión de cómputo; SM bajo pero alto throughput de memoria sugiere comportamiento limitado por memoria.
La respuesta real es profilado: necesitas ver dónde se gasta el tiempo y si los kernels están limitados por ancho de banda.

4) ¿Por qué recibo CUDA OOMs después de horas de entrenamiento?

Causas comunes: fragmentación por formas variables, cachés que crecen o una fuga (almacenar tensores en una lista, acumular grafos).
Vigila la memoria pico en el tiempo, impón límites de forma y no retengas grafos de cómputo accidentalmente.

5) ¿La memoria pinneada siempre ayuda?

Ayuda para transferencias host→device y copias asíncronas, pero demasiada memoria pinneada puede perjudicar al host reduciendo la flexibilidad de memoria pageable.
Úsala con intención: habilítala para buffers de dataloading, no para todo.

6) ¿Por qué el entrenamiento multi-GPU es más lento que en una sola GPU?

Porque añadiste comunicación y sincronización. Si tu lote es demasiado pequeño, all-reduce domina.
Si un worker es más lento (IO, CPU, NUMA), todos esperan. Arregla stragglers y valida la topología NCCL.

7) ¿Debo habilitar siempre la precisión mixta?

Habilítala cuando midas que ayuda y confirmes que no daña la corrección. Algunos modelos necesitan operaciones selectivas en FP32, escalado de loss estable
o hiperparámetros distintos. Trátala como un cambio de ingeniería con pruebas.

8) ¿Por qué el entrenamiento es más rápido cuando copio el dataset a NVMe local?

Porque los sistemas de archivos compartidos a menudo fallan en patrones de acceso con muchos metadatos, muchos archivos pequeños o alta concurrencia.
NVMe local reduce latencia, evita vecinos ruidosos y convierte el “infierno de lecturas aleatorias” en algo que el kernel puede cachear y prefetch.

9) ¿Las actualizaciones de drivers mejoran el rendimiento?

A veces. También pueden degradarlo o romper compatibilidad. Fija versiones, prueba actualizaciones en un canario
y solo despliega cuando puedas medir el beneficio.

10) ¿Cómo evito sorpresas de “GPU corriendo a clocks bajos”?

Monitorea clocks, límites de potencia y razones de throttling. Aplica configuraciones base mediante provisión y alerta sobre desviaciones.
La mayoría de “ralentizaciones misteriosas” son cambios de política, no física.

Conclusión: siguientes pasos que sí puedes tomar

Los mitos duraderos sobre GPUs sobreviven porque reconfortan. “La GPU está infrautilizada” se siente accionable.
“Nuestro layout de almacenamiento provoca contención de metadatos bajo concurrencia” se siente como trabajo real. Haz el trabajo.

Siguientes pasos:

  1. Elige un job representativo y registra una línea base de extremo a extremo: tiempo por paso, throughput, potencia/clocks de GPU y latencia de I/O.
  2. Ejecuta la guía de diagnóstico rápido cuando cambie el rendimiento. No empieces por actualizaciones de drivers; empieza por las restricciones.
  3. Estandariza chequeos de sanidad de nodo (ancho/versión PCIe, afinidad NUMA, clocks, versiones de driver) y difféalos cuando algo cambie.
  4. Arregla primero los cuellos de botella aburridos: formato del dataset, cache local, memoria pinneada y colocación de CPU. Las GPUs recompensan la disciplina.
← Anterior
Ubuntu 24.04: Cron se ejecuta manualmente pero no según lo programado — PATH/Entorno y soluciones
Siguiente →
WordPress no puede subir imágenes: solución rápida para permisos, límites y bibliotecas

Deja un comentario