Análisis de Nsight Compute
NVIDIA Nsight Compute (ncu) perfila kernels CUDA individuales para determinar
por qué son lentos y qué optimizar. Mide el rendimiento de la GPU como un
porcentaje del pico teórico (Velocidad de la Luz / SOL%), lo que permite una
clasificación sistemática de cuellos de botella y una optimización dirigida.
Cuándo Usarlo
Recurre a este skill cuando encuentres:
- Desencadenantes: El usuario quiere perfilar un kernel CUDA, analizar la salida de
ncu, interpretar informes.ncu-rep, o optimizar el rendimiento de kernels GPU - Síntomas: El kernel se ejecuta más lento de lo esperado, baja utilización de la GPU, necesidad de clasificar si está limitado por cómputo o por memoria, problemas de ocupación
- Palabras clave: "ncu", "nsight compute", "SOL%", "speed of light", "perfilado de kernels", "limitado por cómputo", "limitado por memoria", "limitado por latencia", "ocupación", "roofline", "warp stalls", "tasa de aciertos de caché", "ncu-rep"
NO uses este skill para:
- Perfilado a nivel de sistema (usa Nsight Systems /
nsysen su lugar) - Trazado de API CUDA o análisis de línea de tiempo CPU-GPU (usa
nsys) - Monitoreo de GPU sin perfilado (usa
nvidia-smi)
Requisitos
| Dependencia | Versión | Notas |
|---|---|---|
| CUDA Toolkit | >=11.0 | Incluye ncu |
Binario ncu | Uno que el controlador soporte | Nsight Compute 2026.3 necesita un controlador compatible con CUDA 13. O establece la variable de entorno $NCU |
| NVIDIA GPU | Turing+ | Volta necesita Nsight Compute 2025.2 o anterior |
Permisos: ncu puede requerir sudo, CAP_SYS_ADMIN, o --privileged
en contenedores. ncu -v solo imprime la versión; la falta de permisos se muestra
como ERR_NVGPUCTRPERM cuando se perfila el primer kernel.
Principios
Integridad de Datos
Este es un sistema de análisis basado en datos. Cada número que presentes debe tener una fuente autorizada. Sigue estas reglas sin excepción:
- Cita antes de interpretar. Al presentar métricas de la salida de ncu, muestra siempre el comando ncu real que ejecutaste Y la salida cruda relevante (líneas CSV, valores de métricas) antes de afirmar cualquier conclusión numérica.
- Nunca fabriques métricas. Si ncu falla, devuelve una salida inesperada, o no puedes ejecutarlo, dilo explícitamente. No inventes números que parezcan plausibles. Un honesto "el perfilado falló" es mejor que datos fabricados.
- Atribuye cada valor. Para cada métrica que cites (SOL%, duración, ocupación, rendimiento), el lector debe poder rastrearla hasta una línea específica en la salida cruda de ncu que mostraste.
Modelo Mental de SOL%
Velocidad de la Luz (SOL%) mide qué tan cerca ejecuta un kernel del pico teórico de la GPU:
- SOL% de Cómputo (
Rendimiento (SM)) = rendimiento de la unidad SM más ocupada como % de su pico - SOL% de Memoria (
Rendimiento de Memoria) = rendimiento de la unidad de memoria más ocupada (DRAM, L2, L1, memoria compartida) como % de su pico
La métrica más alta generalmente revela el tipo de cuello de botella. Úsala como la señal de clasificación principal. Ambos pueden ser altos a la vez: el kernel está entonces cerca del límite de hardware para su algoritmo.
Umbrales de Clasificación
| % Cómputo | % Memoria | Cuello de Botella | Siguiente Paso |
|---|---|---|---|
| >60 | <40 | Limitado por cómputo | Sección ComputeWorkloadAnalysis |
| <40 | >60 | Limitado por memoria | Sección MemoryWorkloadAnalysis |
| <40 | <40 | Limitado por latencia | Secciones LaunchStats + Occupancy |
| 40-60 | 40-60 | Equilibrado | Perfilar más profundamente con secciones detalladas |
| >60 | >60 | Cerca de los límites del hardware | Cambio algorítmico; revisa ambas secciones de carga de trabajo |
Señales adicionales:
- Duración <10us con muchos lanzamientos -> Limitado por sobrecarga de lanzamiento (usa nsys primero)
- Ambos <40% pero ocupación >50% -> Limitado por instrucciones (revisa InstructionStats)
Niveles de Rendimiento de SOL%
| SOL% | Nivel | Acción |
|---|---|---|
| >80% | Excelente | Solo ajustes menores |
| 60-80% | Bueno | Optimización dirigida |
| 40-60% | Aceptable | Se necesita optimización significativa |
| <40% | Pobre | Se necesita una revisión importante |
Perfilado Basado en Secciones
Usa siempre banderas --section dirigidas en lugar de la recopilación masiva --set. Las secciones individuales son más rápidas y precisas. Solo escala a --set basic o --set detailed cuando se necesite una exploración amplia.
ncu vs nsys
| Herramienta | Alcance | Sobrecarga | Propósito |
|---|---|---|---|
| nsys | A nivel de sistema | 5-10% | Encontrar qué kernels optimizar |
| ncu | A nivel de kernel | 10-100x más lento | Entender por qué un kernel es lento |
Usa nsys primero para identificar los kernels principales por tiempo de GPU, luego ncu para un análisis profundo de esos kernels específicos.
Flujo de Trabajo
Elige tu camino según la solicitud:
- Consulta de conocimiento (qué métricas usar, --section vs --set, cómo filtrar kernels): Responde directamente desde los Principios, Referencia de Comandos y Referencias a continuación. NO ejecutes ncu.
- Diagnóstico rápido (clasificar cuello de botella, verificar SOL%): Solo Paso 1. Escala si el usuario quiere más.
- Diagnóstico específico (conflictos de banco, presión de registros, ocupación): Verificación rápida de SOL% (Paso 1), luego ve directamente a la sección relevante en el Paso 2.
- Análisis profundo (informe detallado, recomendaciones de optimización): Pasos completos 1-5. Presenta el informe estructurado completo con todas las métricas clave (SOL%, duración, ocupación) en tu respuesta final — no dividas el informe entre mensajes ni lo reemplaces con un resumen breve.
Paso 0: Verificar ncu
ncu -v
# O: $NCU -v
Si no se encuentra, asegúrate de que el toolkit CUDA esté instalado o establece la variable de entorno NCU en la ruta del binario.
Paso 1: Diagnóstico SOL%
Comienza siempre con SpeedOfLight para clasificar el cuello de botella:
ncu --section SpeedOfLight --csv \
--kernel-name regex:"KERNEL" \
--launch-skip 5 --launch-count 3 \
-- COMMAND
Lee Rendimiento (SM) y Rendimiento de Memoria de la salida. Clasifica usando los umbrales anteriores.
Paso 2: Escalar con Secciones Dirigidas
Basado en la clasificación del Paso 1, agrega secciones:
| Clasificación | Secciones a Agregar |
|---|---|
| Limitado por cómputo | ComputeWorkloadAnalysis |
| Limitado por memoria | MemoryWorkloadAnalysis |
| Limitado por latencia | LaunchStats, Occupancy |
| Warp stalls | WarpStateStats, SchedulerStats |
| Necesita desglose de instrucciones | InstructionStats |
Incluye siempre LaunchStats y Occupancy al diagnosticar kernels limitados por latencia. Estos revelan presión de registros, límites de memoria compartida y problemas de tamaño de bloque.
Ejemplo -- inmersión profunda en limitado por memoria:
ncu --section SpeedOfLight --section MemoryWorkloadAnalysis --csv \
--kernel-name regex:"embedding_lookup" \
--launch-count 3 \
-- python script.py
Ejemplo -- inmersión profunda en limitado por cómputo:
ncu --section SpeedOfLight --section ComputeWorkloadAnalysis --csv \
--kernel-name regex:"gemm|nvjet" \
--launch-count 3 -- python script.py
Ejemplo -- investigación de ocupación:
ncu --section SpeedOfLight --section LaunchStats --section Occupancy --csv \
--kernel-name regex:"small_kernel" \
-- python script.py
Paso 3: Análisis Roofline (Opcional)
Para una comprensión visual del equilibrio entre cómputo y memoria. Las secciones de roofline
son gráficos: en la CLI solo se imprimen con --print-details all, que lista
los números detrás del gráfico (trabajo y tráfico alcanzados y pico). Para ver el
gráfico, guarda un informe con -o y ábrelo en la interfaz de usuario de Nsight Compute.
ncu --section SpeedOfLight_RooflineChart --print-details all \
--kernel-name regex:"KERNEL" -- COMMAND
Para roofline jerárquico específico de precisión:
# Kernels FP16
ncu --section SpeedOfLight_HierarchicalHalfRooflineChart --print-details all \
--kernel-name regex:"KERNEL" -- COMMAND
# Kernels de tensor core
ncu --section SpeedOfLight_HierarchicalTensorRooflineChart --print-details all \
--kernel-name regex:"KERNEL" -- COMMAND
Interpretación: kernel a la izquierda del punto de cresta = limitado por memoria; a la derecha = limitado por cómputo;
muy por debajo de ambos techos = problema de latencia/ocupación. Consulta references/roofline-analysis.md.
Paso 4: Interpretar y Optimizar
- Identifica el cuello de botella dominante a partir de la clasificación SOL%
- Consulta el análisis detallado y las estrategias de optimización en
references/bottleneck-guide.md - Aplica primero la optimización de mayor impacto
- Vuelve a perfilar para validar la mejora y detectar cambios en el cuello de botella
Paso 5: Validar
Vuelve a perfilar el mismo kernel después de la optimización:
ncu --section SpeedOfLight --csv \
--kernel-name regex:"optimized_kernel" \
--launch-count 3 \
-- python optimized_script.py
Compara: ¿Aumentó el porcentaje de rendimiento? ¿Disminuyó la duración? ¿Cambió el tipo de cuello de botella?
Perfilado de Kernels Compilados JIT (Triton/cuTile/CuTeDSL)
Los kernels compilados JIT activan el ajuste automático en la primera invocación. Aísla la ejecución real:
- Calentamiento primero: Ejecuta el kernel 3-5 veces para completar la compilación JIT y el ajuste automático, luego
torch.cuda.synchronize(). - Usa marcadores de perfilador: Encierra la región medida con
cudaProfilerStart()/cudaProfilerStop(). - Usa
--profile-from-start offpara que ncu solo capture la región marcada:
# Calentamiento (JIT + ajuste automático)
for _ in range(5):
result = kernel(inputs)
torch.cuda.synchronize()
# Perfilar solo estado estable
torch.cuda.cudart().cudaProfilerStart()
for _ in range(3):
result = kernel(inputs)
torch.cuda.synchronize()
torch.cuda.cudart().cudaProfilerStop()
ncu --profile-from-start off --section SpeedOfLight --csv \
--kernel-name regex:"target_kernel" \
--launch-count 3 -- python script.py
Alternativa: usa --launch-skip N para saltar lanzamientos de ajuste automático. Consulta
references/advanced-profiling.md para alternativas de rango NVTX y modo de reproducción.
Análisis Programático de Informes
Extrae métricas de archivos .ncu-rep o .ncu-repz usando el módulo Python ncu_report
(en extras/python/ de la instalación de Nsight Compute):
import ncu_report
ctx = ncu_report.load_report("report.ncu-rep")
for rng in ctx:
for action in rng:
name = action.name()
# "Rendimiento (SM)" y "Rendimiento de Memoria" de SpeedOfLight
compute = action["sm__throughput.avg.pct_of_peak_sustained_elapsed"].as_double()
memory = action["gpu__compute_memory_throughput.avg.pct_of_peak_sustained_elapsed"].as_double()
duration = action["gpu__time_duration.sum"].as_uint64()
if compute > 60:
classification = "limitado por cómputo"
elif memory > 60:
classification = "limitado por memoria"
else:
classification = "limitado por latencia"
print(f"{name}: {classification} (cómputo={compute:.1f}%, mem={memory:.1f}%, {duration}ns)")
Consulta references/python-report-api.md para la API completa (clases IContext, IRange, IAction, IMetric).
Formatos de Salida
Salida CSV (para scripting y análisis automatizado):
ncu --csv --section SpeedOfLight --kernel-name regex:"KERNEL" -- COMMAND
ncu --csv --page raw --section SpeedOfLight -- COMMAND # Todas las métricas planas
El CSV predeterminado tiene una fila por métrica. Sus columnas incluyen ID (el
lanzamiento perfilado), Nombre del Kernel, Nombre de la Sección, Nombre de la Métrica, Unidad de la Métrica
y Valor de la Métrica; los resultados de reglas son filas que llenan Nombre de la Regla,
Descripción de la Regla y Aceleración Estimada en su lugar. Un Nombre de la Métrica puede repetirse
a través de secciones (Rendimiento de Memoria es % en SpeedOfLight y byte/s en
MemoryWorkloadAnalysis), así que filtra también por Nombre de la Sección. --page raw da una
fila por lanzamiento, una columna por métrica y una segunda fila de unidades. Los valores están en
unidades base (ns, hz, %).
Durante el perfilado, las líneas ==PROF== de ncu y la salida propia de la aplicación comparten
stdout con el CSV. Para un CSV limpio, escribe un informe y léelo de vuelta:
Archivos de informe (para análisis posterior):
ncu -o report.ncu-rep --section SpeedOfLight -- COMMAND
ncu --import report.ncu-rep --csv # Una fila por métrica
ncu --import report.ncu-rep --csv --page raw # Una fila por lanzamiento
Proporciona a -o la extensión: sin una, Nsight Compute 2026.3 y versiones posteriores escriben el
report.ncu-repz comprimido con zstd, y versiones anteriores escriben report.ncu-rep.
--import y ncu_report leen ambos.
Filas de métricas clave (valores de Nombre de la Métrica):
| Nombre de la Métrica | Sección | Significado |
|---|---|---|
Duration | SpeedOfLight | Tiempo de ejecución |
Compute (SM) Throughput | SpeedOfLight | % del pico de cómputo |
Memory Throughput | SpeedOfLight | % del pico de la unidad de memoria más ocupada |
SM Frequency | SpeedOfLight | Reloj al que se ejecutó el perfil |
Achieved Occupancy | Occupancy | Warps activos / warps máximos (%) |
Indicadores de éxito:
- Valores de SOL% presentes en la salida -> perfilado exitoso
- Valores de duración razonables (no 0 o extremadamente grandes)
- Múltiples lanzamientos capturados cuando
--launch-count > 1
Ejemplos
Ejemplo: Clasificar un Kernel GEMM
Los kernels GEMM de cuBLAS en Blackwell se llaman nvjet_*, así que coincide con ambos nombres:
ncu --section SpeedOfLight --csv \
--kernel-name regex:"gemm|nvjet" \
--launch-skip 5 --launch-count 3 \
-- python train.py
Salida para una multiplicación de matrices FP16 4096x4096 en B200 (columnas y filas abreviadas):
"ID",...,"Nombre del Kernel",...,"Nombre de la Sección","Nombre de la Métrica","Unidad de la Métrica","Valor de la Métrica",...
"0",...,"nvjet_sm100_hsh_128x256_64x6_2x2f_2cta_h_bz_NNT",...,"GPU Speed Of Light Throughput","Memory Throughput","%","38.38",
"0",...,"nvjet_sm100_hsh_128x256_64x6_2x2f_2cta_h_bz_NNT",...,"GPU Speed Of Light Throughput","Duration","ns","97600",
"0",...,"nvjet_sm100_hsh_128x256_64x6_2x2f_2cta_h_bz_NNT",...,"GPU Speed Of Light Throughput","Compute (SM) Throughput","%","77.11",
Interpretación: limitado por cómputo (77.1% cómputo, 38.4% memoria). Siguiente paso:
verificar el uso de tensor core con --section ComputeWorkloadAnalysis.
Ejemplo: Diagnosticar un Kernel de Embedding Limitado por Memoria
La búsqueda de embedding de PyTorch ejecuta vectorized_gather_kernel, así que también coincide con él:
ncu --section SpeedOfLight --section MemoryWorkloadAnalysis --csv \
--kernel-name regex:"gather|index|embedding" \
--launch-count 3 -- python train.py
Verifica las tasas de aciertos de caché L1/L2 en la salida: las tasas de aciertos bajas sugi
...[truncado para traducción]