Tu GPU está “al 95% de utilización”, el panel está en verde y el cliente sigue quejándose de caídas de frames o picos de latencia en la inferencia.
Bienvenido a la parte de producción donde los promedios engañan y los cuellos de botella se esconden a plena vista.
ROPs, TMUs, SMs y CUs son las partes con nombres poco excitantes que deciden si tu GPU está corriendo a toda máquina, cojeando o esperando por la memoria como si estuviera atascada detrás de un montacargas lento.
Este es el mapa que usas cuando los números no cuadran.
Un modelo mental que resiste cargas reales
Hay dos modos comunes de fallo cuando la gente habla de “rendimiento de GPU”:
(1) tratar la GPU como un solo número (utilización), y
(2) tratar las partes de la GPU como palabras mágicas (“más SMs lo arregla”).
Ambos llevan a errores costosos.
Usa este modelo mental en su lugar: la GPU es una tubería de fábricas especializadas con carreteras compartidas.
Los SMs/CUs son donde ocurre la mayor parte de la aritmética; los TMUs son especialistas en lectura y filtrado de texturas (en gráficos, y a veces relevantes para operaciones similares a muestreos);
los ROPs son donde los píxeles se escriben con pruebas de profundidad/stencil y mezcla.
Todos dependen del ancho de banda de memoria, el comportamiento de las cachés y del driver/runtime para mantener las colas alimentadas.
En inferencia ML, la mayoría de las veces puedes ignorar ROPs y TMUs—pero “la mayoría de las veces” no es “siempre”.
Si haces renderizado, composición, codificación/decodificación de video o ejecutas cargas mixtas en la misma GPU, estos bloques se convierten en fuente de contención.
En gráficos, el balance ROP/TMU importa constantemente.
En términos operativos: los SMs/CUs son tus núcleos de CPU, el ancho de banda de memoria es tu enlace de red, las cachés son tu CDN, y los ROPs/TMUs son aceleradores especializados.
Si sólo miras la “utilización de GPU”, básicamente estás declarando un servicio sano porque top muestra 90% de CPU—y luego te preguntas por qué la latencia p99 está ardiendo.
Una cita que he visto aguantar a lo largo de una década de incidentes: La esperanza no es una estrategia.
— James Cameron.
Si quieres fiabilidad, mides el sistema que realmente tienes, no el que desearías haber comprado.
Anatomía de la GPU: ROPs, TMUs, SMs, CUs (y las partes que la gente olvida)
SMs (NVIDIA) y CUs (AMD): el músculo
NVIDIA los llama Streaming Multiprocessors (SMs).
AMD los llama Compute Units (CUs) (y en arquitecturas más nuevas también oirás hablar de WGPs, o workgroup processors, que agrupan CUs).
Estos son los bloques que ejecutan la mayoría del código de shaders y kernels de cómputo.
Cada SM/CU contiene múltiples carriles de ejecución (piensa en “SIMD/SIMT lanes”), registros, planificadores y almacenamiento local (shared memory / LDS).
Están diseñados para mantener muchos hilos “en vuelo” de modo que cuando un conjunto se atasca (a menudo en memoria), otro pueda correr.
Traducción operativa: los SMs/CUs son motores de rendimiento. Les gusta trabajo consistente y paralelo y se molestan cuando reciben tareas seriales pequeñas,
bifurcaciones pesadas, o patrones de acceso a memoria que parecen confeti derramado.
Dos consecuencias prácticas:
- Ocupación (cuántos warps/wavefronts pueden residir) importa, pero no es un objetivo por sí mismo. A veces una ocupación menor con mejor localidad de memoria gana.
- Presión de registros es un asesino silencioso. Demasiados registros por hilo reducen la ocupación y aumentan los spills a memoria local, que básicamente es “memoria global con gabardina”.
TMUs: unidades de textura (no solo para juegos)
Las Texture Mapping Units (TMUs) tradicionalmente manejan el cálculo de direcciones de textura y el filtrado.
En gráficos, recuperan datos de textura (a menudo con cachés especializadas) y aplican filtrado (bilineal, trilineal, anisotrópico).
Ese es su trabajo principal.
En ML intensivo de cómputo, puede que nunca alcances límites de TMU directamente.
Pero los TMUs pueden aparecer indirectamente cuando:
- Realizas pre/post-procesamiento de imágenes en la GPU.
- Usas rutas aceleradas por hardware de muestreo en APIs de gráficos.
- Tienes cargas mixtas—renderizado más cómputo—compartiendo el mismo chip.
Si tu carga depende mucho de fetch de texturas, los TMUs pueden convertirse en cuello de botella incluso con capacidad de shader/compute de sobra.
En ese caso “más SMs” no te salvará.
ROPs: el departamento de escritura
Las ROPs (Raster Operations Pipelines) son responsables de tomar los datos de píxeles listos para aterrizar en un framebuffer y hacer los pasos finales:
mezcla, pruebas de profundidad/stencil y escritura a memoria.
Si recuerdas una cosa: los ROPs se ocupan de escribir píxeles, y escribir píxeles suele exigir mucho ancho de banda de memoria.
Los cuellos de botella de ROP aparecen en cargas gráficas con:
- Altas resoluciones (4K y más allá)
- Mucho overdraw
- Mezclas intensas (transparencia, post-procesado)
- MSAA (más muestras escritas)
En entornos solo de cómputo, puede que no pienses en ROPs en absoluto—y está bien—hasta que ejecutes composición GPU, captura de pantalla, escritorio remoto u overlays de video en la misma GPU.
Entonces descubres que los bloques “irrelevantes” compartían ancho de banda de memoria y cachés con tu kernel “importante”.
Sistema de memoria: la parte que arruina tu día
El subsistema de memoria de la GPU es la combinación de HBM/GDDR, controladoras de memoria, caché L2 y enlaces que mueven datos entre los SMs/CUs y la VRAM.
Frecuentemente es el cuello de botella real, y no le importan tus TFLOPS teóricos.
Si tus kernels están limitados por memoria, añadir más cómputo no ayudará.
Si estás limitado por ancho de banda, la jugada ganadora suele ser una de:
mejor localidad de memoria, mover menos bytes, más fusión de operaciones, menor precisión (cuando sea seguro),
o simplemente usar una GPU con más ancho de banda.
Planificadores, colas y el problema de “alimentado vs hambriento”
Una GPU puede estar completamente sana y aun así subutilizada si el host no puede alimentarla:
contención de hilos de CPU, cuellos de botella del GIL de Python, transferencias síncronas, batches pequeños, dataloaders lentos, o un driver atascado en serialización.
“La GPU está al 20%” no es un problema de GPU hasta que demuestras que lo es.
Núcleos Tensor, núcleos RT y aliados: bloques especializados que cambian las matemáticas
Las GPUs modernas tienen unidades de ejecución especializadas (Tensor Cores de NVIDIA, unidades de matriz de AMD, núcleos RT).
Estas no son SMs/CUs, pero conviven con ellos y pueden cambiar dramáticamente las características de rendimiento.
También son fuente común de confusión: un kernel puede ser intensivo en cómputo pero no usar las unidades rápidas de matrix por el tipo de dato, el layout o la selección del kernel.
Broma #1: Una GPU es como una cocina de restaurante—si el lavaplatos (ancho de banda de memoria) es lento, contratar más chefs (SMs) solo crea pilas más altas de platos sucios.
Hechos interesantes y breve historia (que realmente ayuda)
- Los ROPs anteceden al “GPU compute” tal como lo conocemos. Eran centrales cuando las tuberías gráficas eran más de función fija, y escribir píxeles eficientemente lo era todo.
- Las primeras eras de “shader model” hicieron del balance SM/TMU una estrategia de producto. Los fabricantes afinaban chips para cargas de juego donde el fetch de texturas + aritmética tenían ratios específicos.
- CUDA (era 2007) ayudó a rebrandear los SMs como motores de propósito general. De repente el mismo silicio que dibujaba triángulos hacía álgebra lineal y simulaciones.
- La terminología CU de AMD vino de un cambio similar. “Compute Unit” es un nombre que suena como si debiera ser programado por un compilador, no por un driver de gráficos.
- Las cachés de texturas influyeron en patrones de cómputo. Algunos algoritmos usaban accesos tipo textura porque esa ruta tenía comportamiento de caché que las cargas generales no igualaban en ese momento.
- La tasa de relleno solía ser una especificación destacada. El fillrate de píxeles (a menudo ligado al conteo de ROP y reloj) importaba más cuando el shading era más simple y el ancho de salida era un muro rígido.
- El ancho de banda de memoria ha sido la carrera armamentista de fondo. Las generaciones de GDDR y HBM no fueron mejoras cosméticas; atendieron un cuello de botella que las mejoras de cómputo seguían sobrepasando.
- El cómputo asincrónico y la mejor planificación cambiaron el significado de “utilización”. Un número alto de utilización puede ocultar contención de colas o solapamientos subóptimos entre copy/compute/gráficos.
- Las GPUs modernas son multi-tenant por diseño. Preempción, multi-instance GPU (MIG) y características de virtualización existen porque la producción demandó aislamiento—no porque los gamers lo pidieran amablemente.
Qué medir y por qué: las métricas que importan
Si eres responsable del rendimiento y la fiabilidad, necesitas saber qué subsistema está saturado:
cómputo, ancho de banda de memoria, cachés, PCIe/NVLink, tubería gráfica, o la cadena de alimentación del host.
El trabajo no es “subir la utilización de GPU”. El trabajo es “cumplir SLOs con coste predecible”.
Limitado por cómputo vs limitado por memoria: deja de adivinar
Una carga limitada por cómputo escala con:
más SMs/CUs, relojes más altos, mejor mezcla de instrucciones, mejor uso de unidades tensor/matrix.
Una carga limitada por memoria escala con:
más ancho de banda, mejor tasa de aciertos de caché, mejor coalescencia, menos lecturas/escrituras, fusión.
“Pero mi utilización es alta” es compatible con ambos casos.
Por eso también observas el throughput de memoria y las razones de stall en los perfiles.
ROPs y TMUs: cuándo importan
Si operas cargas gráficas (granjas de render, VDI, streaming de juegos, CAD), necesitas claridad por cuadro en la tubería:
¿estás limitado por shading (SM/CU), fetch/filtrado de texturas (TMU) o escritura/salida/blend (ROP)?
Los síntomas difieren:
- Limitado por ROP: aumentar la resolución perjudica desproporcionadamente; la mezcla intensa mata; el ancho de banda sube.
- Limitado por TMU: escenas ricas en texturas se desploman aunque la utilización ALU no esté al máximo.
- Limitado por SM/CU: shaders complejos, mucho cómputo por píxel, ray marching, matemáticas pesadas.
Las métricas “trampa” operativas
- Límite de potencia / throttling: si la GPU está limitada por potencia o térmica, tus números “esperados” son ficción.
- Errores ECC / remapeo de memoria: las funciones de fiabilidad pueden cambiar rendimiento; los errores pueden degradar el throughput o disparar retiradas.
- Replays PCIe / ancho de banda: las transferencias host-dispositivo pueden dominar cuando el batch es pequeño o haces demasiadas copias.
- Context switching / contención multi-proceso: múltiples jobs pueden pelear por caché, ancho de banda de memoria y tiempos de ejecución.
- Dominios de reloj: el reloj de memoria y el reloj de SM pueden comportarse diferente bajo límites.
Tareas prácticas: comandos, salidas y decisiones (12+)
Estas son tareas de “estoy de guardia y necesito respuestas”. Cada una incluye: un comando, qué significa la salida y la decisión que tomas.
Asume Linux, herramientas NVIDIA cuando corresponda, y que tienes permiso para mirar la máquina que pagas.
(AMD tiene herramientas comparables; la lógica es la misma aunque el comando difiera.)
Task 1: Confirmar modelo de GPU, driver y salud básica
cr0x@server:~$ nvidia-smi
Tue Jan 13 12:44:10 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. |
|===============================+======================+======================|
| 0 NVIDIA A10 On | 00000000:17:00.0 Off | 0 |
| 30% 62C P0 138W / 150W | 19750MiB / 24576MiB | 92% Default |
+-------------------------------+----------------------+----------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
|=============================================================================|
| 0 N/A N/A 18342 C python 19600MiB|
+-----------------------------------------------------------------------------+
Qué significa: Confirma versión de driver/CUDA, modelo de GPU, uso de potencia, temperatura, uso de memoria, utilización y qué proceso posee VRAM.
Decisión: Si la memoria está casi llena, sospecha fragmentación/riesgo de OOM; si la potencia está al límite con Perf state alto, revisa throttling; si GPU-Util alto pero throughput bajo, profundiza (memoria o stalls).
Task 2: Comprobar razones de throttling (potencia/térmica/voltaje)
cr0x@server:~$ nvidia-smi -q -d PERFORMANCE | sed -n '1,120p'
==============NVSMI LOG==============
Timestamp : Tue Jan 13 12:44:17 2026
Driver Version : 550.54.14
CUDA Version : 12.4
Performance State : P0
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
SW Thermal Slowdown : Not Active
Qué significa: “SW Power Cap: Active” significa que estás alcanzando el límite de potencia configurado; los relojes pueden reducirse para mantenerse dentro de él.
Decisión: Si controlas térmicas y potencia, sube el límite de potencia (dentro de la especificación) o mejora la refrigeración. Si no, ajusta expectativas y planificación de capacidad.
Task 3: Vigilar utilización, relojes, potencia y memoria en tiempo real
cr0x@server:~$ nvidia-smi dmon -s pucvmt -d 1
# gpu pwr gtemp mtemp sm mem enc dec mclk pclk
# Idx W C C % % % % MHz MHz
0 149 69 - 78 94 0 0 5001 1710
0 150 70 - 79 95 0 0 5001 1710
0 150 70 - 80 95 0 0 5001 1710
Qué significa: Obtienes una vista en serie temporal. Si SM% es alto pero mem% también es alto, podrías estar limitado por memoria o reventando cachés.
Decisión: Si mem% está clavado y el rendimiento es plano, céntrate en los bytes movidos (batching, fusión, precisión). Si SM% es bajo, enfócate en alimentar la GPU (CPU, dataloader, overhead de lanzamientos).
Task 4: Comprobar ancho y velocidad del enlace PCIe (límites de alimentación del host)
cr0x@server:~$ nvidia-smi -q -d PCI | sed -n '1,120p'
PCI
Bus : 0x17
Device : 0x00
Domain : 0x0000
Bus Id : 00000000:17:00.0
PCIe Generation
Max : 4
Current : 3
Link Width
Max : 16x
Current : 8x
Qué significa: La tarjeta soporta Gen4 x16 pero actualmente está funcionando en Gen3 x8. Eso es una gran reducción en el ancho de banda host-dispositivo.
Decisión: Reasienta, mueve a otros slots, revisa ajustes BIOS, comprueba risers y verifica el reparto de líneas de la placa. Si tu carga es intensiva en transferencias, esto puede ser toda la historia.
Task 5: Observar uso por proceso de la GPU (contención multi-tenant)
cr0x@server:~$ nvidia-smi pmon -c 1
# gpu pid type sm mem enc dec command
# Idx # C/G % % % % name
0 18342 C 78 92 0 0 python
0 27711 C 12 7 0 0 python
Qué significa: Dos procesos de cómputo comparten la GPU. El pequeño aún te cuesta: cambios de contexto, presión de caché y contención de ancho de banda de memoria.
Decisión: Si necesitas SLOs de latencia, aísla las cargas (GPUs separadas, MIG, políticas de scheduling). Si el objetivo es throughput, la colocalización puede estar bien pero mide la interferencia.
Task 6: Revisar logs del driver kernel por resets o errores Xid
cr0x@server:~$ sudo journalctl -k --since "2 hours ago" | egrep -i "NVRM|Xid|gpu|pcie" | tail -n 20
Jan 13 11:52:03 server kernel: NVRM: Xid (PCI:0000:17:00): 31, pid=18342, Ch 0000002b, MMU Fault: ENGINE GRAPHICS GPCCLIENT_T1_0 faulted @ 0x7f3a0000
Jan 13 11:52:03 server kernel: NVRM: Xid (PCI:0000:17:00): 31, pid=18342, Ch 0000002b, MMU Fault: Fault type: UNBOUND_INST
Qué significa: Los errores Xid suelen indicar fallos de driver, hardware o a nivel de aplicación (accesos inválidos a memoria, PCIe malo, relojes inestables).
Decisión: Si los Xid se repiten: pon en cuarentena el host/GPU, reproduce bajo carga controlada, actualiza driver/firmware, ejecuta tests de estrés y considera RMA si crece la sospecha de hardware.
Task 7: Confirmar que la CPU no es el verdadero cuello de botella (alimentando la GPU)
cr0x@server:~$ mpstat -P ALL 1 3
Linux 6.8.0 (server) 01/13/26 _x86_64_ (64 CPU)
12:44:43 PM CPU %usr %nice %sys %iowait %irq %soft %steal %idle
12:44:44 PM all 92.1 0.0 7.1 0.0 0.0 0.3 0.0 0.5
12:44:44 PM 7 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
12:44:44 PM 8 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
Qué significa: Las CPUs están saturadas; un par de cores están completamente ocupados. Si tu trabajo GPU se lanza desde un bucle de un solo hilo, puedes dejar hambriento al dispositivo.
Decisión: Perfiliza la tubería del host: hilos del dataloader, preprocesado, serialización, overhead de Python. Aumenta el batch, usa pipelines asíncronos o mueve el preprocesado a la GPU.
Task 8: Comprobar localidad NUMA (los dispositivos PCIe odian el tráfico cross-socket)
cr0x@server:~$ nvidia-smi topo -m
GPU0 CPU Affinity NUMA Affinity
GPU0 X 0-31 0
Qué significa: GPU0 está ligada al nodo NUMA 0; la afinidad de CPU recomendada es 0-31. Ejecutar el hilo alimentador en el otro socket añade latencia y reduce el ancho de banda PCIe efectivo.
Decisión: Fija los hilos de CPU al nodo NUMA correcto y asigna memoria del host local a ese nodo para las transferencias.
Task 9: Verificar rendimiento efectivo de PCIe durante transferencias
cr0x@server:~$ nvidia-smi dmon -s t -d 1
# gpu rxpci txpci
# Idx MB/s MB/s
0 5210 4980
0 5400 5102
0 5305 5055
Qué significa: El throughput RX/TX PCIe está alrededor de ~5 GB/s. Si esperabas comportamiento Gen4 x16, estás alimentando insuficientemente el dispositivo.
Decisión: Reduce transferencias (mantén datos en GPU más tiempo, fusiona ops), aumenta el tamaño de batch, usa memoria pinned y arregla problemas de enlace PCIe si están presentes.
Task 10: Comprobar info de memoria GPU y riesgo de fragmentación
cr0x@server:~$ nvidia-smi --query-gpu=memory.total,memory.used,memory.free --format=csv
memory.total [MiB], memory.used [MiB], memory.free [MiB]
24576 MiB, 24010 MiB, 566 MiB
Qué significa: Estás prácticamente sin VRAM. Incluso si “cabe”, la fragmentación del allocador o un pico súbito puede causar OOM.
Decisión: Reduce modelo/batch, activa optimizaciones de memoria (checkpointing de activaciones cuando sea apropiado), o aísla esta carga de cualquier otra cosa que use VRAM.
Task 11: Identificar si la GPU está haciendo trabajo gráfico/display (involucra ROPs)
cr0x@server:~$ nvidia-smi --query-gpu=display_active,display_mode --format=csv
display_active, display_mode
Disabled, Disabled
Qué significa: No hay display conectado y el modo display está desactivado. Bien: menos sorpresas por composición/efectos de escritorio.
Decisión: Si el display está activo en una GPU de cómputo en producción, considera configuración headless o una GPU separada para display/VDI. El uso mixto es como se obtiene “jitter misterioso”.
Task 12: Comprobar ajustes de reloj de GPU (alguien te “optimizó” hasta un rincón)
cr0x@server:~$ nvidia-smi -q -d CLOCK | sed -n '1,120p'
Clocks
Graphics : 1710 MHz
SM : 1710 MHz
Memory : 5001 MHz
Applications Clocks
Graphics : 1410 MHz
Memory : 5001 MHz
Qué significa: Los application clocks están fijados por debajo de los relojes máximos de graphics/SM. Eso puede limitar el rendimiento aunque las térmicas estén bien.
Decisión: Si esto no es intencional, restablece los application clocks o fíjalos explícitamente según tu estrategia de rendimiento/potencia.
Task 13: Verificar el modo de cómputo y el modo de persistencia (comportamiento multi-usuario)
cr0x@server:~$ nvidia-smi --query-gpu=compute_mode,persistence_mode --format=csv
compute_mode, persistence_mode
Default, Enabled
Qué significa: El modo de cómputo por defecto permite múltiples procesos; la persistencia activada evita overheads repetidos de inicialización y puede reducir la latencia del primer job.
Decisión: Para aislamiento estricto, considera Exclusive Process (donde aplique). Mantén persistence activada para comportamiento estable en producción.
Task 14: Confirmar que hugepages/IOMMU no sabotean DMA (chequeos a nivel host)
cr0x@server:~$ dmesg | egrep -i "iommu|DMAR|vfio" | tail -n 10
[ 0.612345] DMAR: IOMMU enabled
[ 0.612900] DMAR: Intel(R) Virtualization Technology for Directed I/O
Qué significa: IOMMU está habilitado. Esto puede estar bien, pero las malas configuraciones pueden causar overhead o límites de mapeo en ciertos setups.
Decisión: Si ves latencias inusuales en transferencias o errores de mapeo, valida los ajustes de IOMMU para tu entorno (especialmente con passthrough/virtualización).
Task 15: Chequeo rápido “¿esto es limitado por memoria?” usando throughput observado
cr0x@server:~$ nvidia-smi --query-gpu=utilization.gpu,utilization.memory --format=csv -l 1
utilization.gpu [%], utilization.memory [%]
91 %, 96 %
92 %, 97 %
90 %, 96 %
Qué significa: Alta utilización de memoria junto a alta utilización de GPU suele apuntar a kernels limitados por memoria o tráfico de memoria intenso (incluyendo spills).
Decisión: Pasa al profiling: revisa throughput de memoria, tasas de aciertos de caché y razones de stalls a nivel de kernel. No pierdas tiempo afinando aritmética primero.
Guía de diagnóstico rápido: encuentra el cuello de botella en minutos
Este es el camino de “no te pierdas en capturas de perfilador”. Está optimizado para triage en producción.
El objetivo: identificar si estás limitado por alimentación, cómputo, ancho de banda de memoria, tubería gráfica (TMU/ROP), o throttling/fallos.
Primero: sanidad y salud (30–60 segundos)
- Ejecuta
nvidia-smi. Revisa: errores, temperaturas, potencia, uso de memoria, procesos activos. - Revisa logs del kernel por eventos Xid/reset (
journalctl -k). - Revisa razones de throttling (
nvidia-smi -q -d PERFORMANCE).
Si encuentras resets, picos de ECC o Xids repetidos, deja de perseguir rendimiento. Ahora estás depurando fiabilidad.
Segundo: ¿se está alimentando la GPU? (2–3 minutos)
- Mira la saturación de CPU (
mpstat/top). - Revisa el estado del enlace PCIe (Gen/width) y throughput PCIe (
nvidia-smi -q -d PCI,nvidia-smi dmon -s t). - Revisa afinidad NUMA (
nvidia-smi topo -m).
Si la CPU está clavada o PCIe está degradado (sorpresa Gen3 x8), tienes un problema de plataforma, no de kernel.
Tercero: clasifica el cuello de botella por comportamiento (5–10 minutos)
- Limitado por cómputo: SM ocupados alto, uso de memoria moderado; escalable con relojes; mejora con tensor cores activados.
- Limitado por memoria: uso de memoria alto, rendimiento plano al subir relojes SM, sensible al tamaño de batch y fusión.
- Limitado por TMU/texturas (gráficos): escenas con muchas texturas se desploman; cambios en muestreo/filtrado afectan más que la aritmética del shader.
- Limitado por ROP/salida (gráficos): resolución y mezcla afectan mucho; las escrituras de salida dominan; MSAA empeora más de lo esperado.
Tu próxima herramienta depende de la clasificación. Si estás limitado por cómputo, optimiza kernels y matemáticas. Si estás limitado por memoria, reduce tráfico y mejora localidad.
Si estás limitado por ROP/TMU, ajusta la configuración de render o elige hardware con un balance distinto.
Errores comunes: síntoma → causa raíz → arreglo
1) “La utilización de GPU es alta pero el throughput es bajo”
Síntoma: GPU-Util 90%+, pero frames/sec o inferences/sec son decepcionantes.
Causa raíz: Kernels limitados por memoria, thrash de caché, spills de registros, o contención de otros procesos.
Arreglo: Confirma utilización de memoria y comportamiento de ancho de banda; perfila por stalls/spills; fusiona kernels; reduce precisión donde sea seguro; aísla cargas.
2) “La utilización de GPU es baja pero la latencia es alta”
Síntoma: GPU-Util 10–30%, sin embargo la latencia p99 es mala.
Causa raíz: Cuello de botella en la alimentación desde el host (preprocesado de CPU, batches pequeños, copias síncronas), o overhead de lanzamiento de kernels dominando.
Arreglo: Aumenta el tamaño de batch, pipelinea trabajo CPU/GPU, usa transferencias asíncronas, fija hilos de CPU a cores NUMA-locales, y reduce lanzamientos por petición.
3) “El rendimiento varía mucho entre servidores idénticos”
Síntoma: Mismo modelo de GPU, un servidor es 20–40% más lento.
Causa raíz: Entrenamiento del enlace PCIe a Gen/width reducida, diferentes límites de potencia, condiciones térmicas o ajustes BIOS.
Arreglo: Compara nvidia-smi -q -d PCI y razones de throttling; estandariza firmware/BIOS, valida refrigeración, arregla asignación de líneas.
4) “El render se desploma al activar transparencia o mayor resolución”
Síntoma: Una escena va bien hasta que añades transparencia/post-procesado; mayor resolución hunde los FPS.
Causa raíz: ROP/salida y ancho de banda limitados; mucha mezcla y overdraw incrementan el tráfico de escritura.
Arreglo: Reduce overdraw, optimiza pases de mezcla, considera buffers de menor precisión donde sea aceptable, y vigila el ancho de banda de memoria. Hardware con más ROPs/ancho de banda ayuda.
5) “Escenas ricas en texturas son lentas aunque los shaders no sean complejos”
Síntoma: Matemáticas simples, pero el rendimiento se hunde con texturas de alta resolución y filtrado.
Causa raíz: Limitación por TMU/fetch de texturas; misses en la caché de texturas; coste del filtrado anisotrópico.
Arreglo: Ajusta LODs de texturas, reduce niveles de filtrado, comprime texturas adecuadamente, disminuye muestreo aleatorio y elige SKU de GPU con mejor rendimiento de texturas si es necesario.
6) “Después de actualizar el driver, todo está más lento”
Síntoma: Mismo código, menor throughput, posiblemente comportamiento de potencia distinto.
Causa raíz: Cambios en relojes/potencia por defecto, selección de kernel alterada, o nuevas mitigaciones de seguridad.
Arreglo: Revisa application clocks y límites de potencia; valida con benchmarks controlados; fija versiones conocidas buenas cuando necesites rendimiento determinista.
7) “Compramos una GPU más grande y obtuvimos poca mejora”
Síntoma: Más SMs/TFLOPS, pero solo una pequeña mejora.
Causa raíz: Estabas limitado por memoria o PCIe; compraste cómputo pero necesitabas ancho de banda o mejor pipeline de datos.
Arreglo: Mide transferencias y throughput de memoria; elige GPUs con más ancho de banda (HBM), interconexión más rápida (NVLink), o rediseña el camino de datos.
Broma #2: La forma más fácil de duplicar el rendimiento de la GPU es dejar de mandarle el mismo tensor tres veces—lamentablemente, esto es más común de lo que debería ser.
Tres micro-historias corporativas desde el terreno
Micro-historia 1: El incidente causado por una suposición equivocada (los ROPs no importan… hasta que importan)
Una compañía operaba una flota GPU para análisis de video en tiempo real: decodificar, inferir, superponer cajas y re-encodificar.
Lo trataron como “principalmente cómputo”, así que el modelo de capacidad se basó en la utilización de SM y VRAM.
Parecía limpio. También estaba equivocado.
Durante un lanzamiento de producto, las superposiciones se volvieron más complejas: más etiquetas, elementos UI con alpha blend, y algo de post-procesado extra.
Los graphs de cómputo se mantuvieron cómodos. Pero los streams de cliente empezaron a perder frames y la latencia p95 subió.
Los ingenieros persiguieron kernels, ajustaron tamaños de batch e incluso retrocedieron un modelo. Nada funcionó.
El culpable real fue la composición de salida: mezclar y escribir los frames de vuelta estaba golpeando el subsistema de memoria y las etapas finales de píxeles.
En otras palabras, la tubería se volvió más ROP-ish y exigente en ancho de banda.
La GPU estaba “ocupada”, pero no en la forma que el modelo asumía.
Arreglarlo fue poco romántico:
redujeron el overdraw de overlays, cambiaron la estrategia de composición para minimizar pases de mezcla, y separaron responsabilidades—cómputo en una GPU, compositor/encode en otra en los nodos más cargados.
Tras eso, el sistema volvió a escalar previsiblemente. La lección no fue “los ROPs importan”. La lección fue “las suposiciones cuestan caro”.
Micro-historia 2: La optimización que salió mal (perseguir ocupación hasta un barranco)
Otro equipo tenía un kernel CUDA que iba más lento de lo esperado. Alguien encontró un post que decía “maximiza la ocupación”.
Refactorizaron el kernel para usar menos registros y aumentaron la ocupación. La captura del perfil parecía mejor.
El throughput en producción empeoró.
El cambio redujo el uso de registros, pero también incrementó el tráfico a memoria global al recomputar valores y cargar intermedios.
El kernel pasó de “moderadamente limitado por cómputo” a “dolorosamente limitado por memoria.”
La ocupación subió. El rendimiento cayó. Los gráficos engañaron porque no estaban midiendo el límite correcto.
El arreglo fue revertir el enfoque de “ocupación a cualquier costo”:
aceptar ocupación menor, mantener valores críticos en registros y reestructurar accesos a memoria para ser más coalescentes.
También fusionaron dos kernels adyacentes para evitar escribir un tensor intermedio a VRAM.
La ocupación parecía peor; el throughput mejoró materialmente.
El seguimiento operativo fue aún más valioso: añadieron una puerta de rendimiento en CI que ejecutaba kernels representativos y comparaba throughput de memoria y distribuciones de tiempo de ejecución.
El siguiente cambio “ingenioso” se detectó antes de llegar a producción.
Micro-historia 3: La práctica aburrida pero correcta que salvó el día (estandarizar PCIe y potencia)
Un equipo de plataforma operaba servidores GPU mixtos adquiridos en distintas olas de compra.
Mismo modelo de GPU en papel, pero diferentes placas base, versiones de BIOS y flujo de aire en el chasis.
Tenían una regla poco glamorosa: cada nodo debía pasar una prueba de aceptación de “líneas y relojes” antes de unirse al clúster.
La prueba era aburrida: comprobar PCIe Gen/width, ejecutar un benchmark de transferencia corto, confirmar límite de potencia, confirmar relojes bajo carga sostenida, comprobar que no hubiera errores Xid.
Es el tipo de cosa que la gente llama burocracia hasta que están de guardia a las 3 a.m.
Un fin de semana, llegó un lote de nodos con una configuración de riser que silenciosamente entrenaba la GPU a un ancho de enlace reducido.
Sin la puerta de aceptación, esos nodos se habrían añadido al pool y habrían causado jobs lentos al azar, timeouts intermitentes y un flujo interminable de tickets de rendimiento.
En cambio, la puerta los rechazó inmediatamente. Se arreglaron antes de que los clientes los vieran.
La victoria no fue “atrapamos un bug”. La victoria fue prevenir toda una clase de comportamiento inestable de entrar al sistema.
La producción ama las comprobaciones aburridas y repetibles.
Listas de verificación / plan paso a paso
Checklist A: Cuando alguien dice “la GPU está lenta”
- Identifica el tipo de carga: solo cómputo, solo gráficos, o mixta (incluye decodificar/encode/display/compositor).
- Verifica salud de la GPU:
nvidia-smi, versiones de driver, temperaturas, potencia, errores. - Revisa razones de throttling: tope de potencia, slowdown térmico, application clocks.
- Confirma enlace de plataforma: PCIe Gen/width, localidad NUMA, throughput PCIe bajo carga.
- Revisa contención multi-tenant: uso por proceso; confirma suposiciones de scheduling/aislamiento.
- Clasifica el cuello de botella: limitado por cómputo vs memoria vs alimentación; para gráficos considera TMU/ROP.
- Sólo entonces abre el perfilador—y ve con una hipótesis.
Checklist B: Antes de comprar hardware o redimensionar un clúster
- Mide el cuello de botella actual (no sólo la utilización).
- Si estás limitado por memoria, prioriza mejoras de ancho de banda/caché y cambios de software sobre más cómputo.
- Si estás limitado por transferencias, prioriza interconexión y localidad de datos (PCIe Gen, NVLink, pinning NUMA).
- Si estás limitado por ROP/TMU (gráficos), elige SKUs con el balance apropiado; no compres cómputo que no puedas alimentar o escribir.
- Planifica aislamiento: MIG, GPUs dedicadas para servicios sensibles a latencia, o al menos enforcement a nivel cgroup y scheduler.
- Estandariza pruebas de aceptación: ancho de línea, relojes bajo carga, límites de potencia, logs de errores limpios.
Checklist C: Bucle seguro de afinamiento de rendimiento (el que no crea incidentes)
- Elige una carga representativa. No un microbenchmark a menos que ese microbenchmark sea tu realidad de producción.
- Registra líneas base: throughput, distribución de latencias, potencia, temperaturas, uso de memoria, throughput PCIe.
- Cambia una cosa. Una.
- Vuelve a medir y compara distribuciones, no sólo medias.
- Despliega sólo si entiendes por qué mejoró y puedes explicar los nuevos modos de fallo.
- Añade una puerta de regresión si el cambio importa (job CI, canario o corrida nocturna de rendimiento).
Preguntas frecuentes
1) ¿Cuál es la definición más simple de SMs y CUs?
Son los bloques principales de ejecución que corren hilos paralelos para shaders y kernels de cómputo.
NVIDIA los llama SMs; AMD los llama CUs. Internos distintos, rol similar: hacer matemáticas y ocultar latencia con mucho trabajo paralelo.
2) ¿Son “CUDA cores” lo mismo que SMs?
No. “CUDA cores” es un conteo orientado al marketing de carriles ALU escalares a través de todos los SMs.
Un SM es la unidad que planifica y gestiona el trabajo; contiene múltiples unidades de ejecución, registros y memoria compartida.
3) ¿Qué hacen realmente los TMUs y por qué debería importarme?
Los TMUs recuperan datos de textura y aplican filtrado eficientemente. En gráficos, los límites de TMU son reales y visibles.
En cómputo, importan cuando tu carga usa rutas de muestreo tipo textura o cuando cargas mixtas causan contención por memoria/caché.
4) ¿Qué hacen los ROPs y cuándo son un cuello de botella?
Los ROPs manejan operaciones finales de píxeles: mezcla, profundidad/stencil y escritura de píxeles al framebuffer.
Se convierten en cuello de botella cuando las escrituras de salida dominan: alta resolución, mezcla intensa, mucho overdraw, MSAA o escenarios limitados por ancho de banda.
5) ¿Por qué aumentar la resolución perjudica tanto el rendimiento a veces?
Más píxeles significa más trabajo en las etapas finales de la tubería y más tráfico de memoria.
Si estás limitado por ROP/ancho de banda, duplicar el conteo de píxeles puede hundir los FPS aunque el cómputo no esté al máximo.
6) ¿Por qué la utilización de GPU es baja aunque mi programa “use la GPU”?
Razones comunes: cuellos de botella de preprocesado en CPU, tamaños de batch pequeños, copias host-dispositivo síncronas, overhead de lanzamiento de kernels, o espera por I/O.
Baja utilización suele significar que la GPU está inactiva esperando trabajo.
7) ¿Es buena siempre la alta ocupación?
No. La ocupación es una herramienta para ocultar latencia, no un trofeo.
Para algunos kernels, mayor ocupación incrementa tráfico de memoria o fuerza spills. La condición de victoria es throughput y latencia bajo carga real, no una sola métrica.
8) ¿Cómo se relacionan ROPs/TMUs con la inferencia ML?
Usualmente no—hasta que ejecutes pre/post-procesado, composición o cargas de video en la misma GPU.
Además, cualquier cosa que aumente la presión de ancho de banda de memoria puede perjudicar indirectamente el throughput ML, aun si ROPs/TMUs no se usan directamente.
9) ¿Cuál es la forma más rápida de saber si estoy limitado por memoria?
Observa la utilización y throughput de memoria bajo carga, y luego cambia algo que debería aumentar cómputo (como relojes SM o un SKU de cómputo más rápido).
Si el rendimiento apenas cambia, probablemente estás limitado por memoria. Confírmalo con perfilado de stalls/bandwidth.
10) ¿Debería compartir GPUs entre servicios en producción?
Solo si puedes tolerar la interferencia y la mides.
Para cargas sensibles a latencia, aísla con GPUs dedicadas o MIG/particionamiento. “Funcionó en staging” no es una política de scheduling.
Conclusión: siguientes pasos prácticos
ROPs, TMUs, SMs y CUs no son trivia. Son un mapa de dónde puede atascarse tu trabajo.
Cuando diagnosticas por etapa de la tubería—alimentación, cómputo, memoria, salida—dejas de adivinar y empiezas a arreglar.
Siguientes pasos que devuelven valor de inmediato:
- Añade una prueba ligera de aceptación de nodo GPU: PCIe Gen/width, relojes sostenidos bajo carga, sin Xids, potencia/temperaturas estables.
- Instrumenta tus servicios con throughput y distribuciones de latencia junto a métricas de GPU/CPU/PCIe. Los promedios son bonitos. El p99 paga tu salario.
- Cuando el rendimiento regrese, ejecuta la guía de diagnóstico rápido antes de tocar código. La mitad de los “problemas de GPU” son de plataforma y tubería.
- Para cargas gráficas/mixtas, considera explícitamente TMU/ROP y restricciones de ancho de banda. Si no modelos el coste de salida, él te modelará a ti.