jiweibo/perf-nsight-compute-analysis

Analyse des résultats de profilage `ncu` (NVIDIA Nsight Compute) : classification des goulots d'étranglement SOL%, analyse roofline, diagnostic d'occupation, analyse de la hiérarchie mémoire, analyse des stalls de warp, interprétation des métriques et analyse programmatique des rapports .ncu-rep. Ne concerne PAS l'écriture de kernels ou la génération de code, Nsight Systems (nsys), le profilage côté hôte ou le profilage au niveau système.

Qu'est-ce que perf-nsight-compute-analysis ?

Ce skill permet d'analyser en profondeur les performances des kernels CUDA à l'aide de NVIDIA Nsight Compute (`ncu`). Il guide l'utilisateur à travers un workflow structuré pour identifier et classer les goulots d'étranglement (compute-bound, memory-bound, latency-bound) en utilisant le modèle Speed of Light (SOL%). Le skill automatisé interprète les métriques clés comme l'occupation, les taux de succès du cache et les stalls de warp, et propose des stratégies d'optimisation ciblées. Il supporte le profilage des kernels JIT-compilés (Triton, cuTile, CuTeDSL) et l'analyse programmatique des rapports `.ncu-rep` via le module Python `ncu_report`. Il est particulièrement utile pour les développeurs GPU qui cherchent à optimiser les performances de leurs kernels CUDA, en fournissant une analyse reproductible et basée sur les données, avec des recommandations précises pour chaque classe de goulot d'étranglement.

Compatible avec✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/jiweibo/skills/tree/HEAD/perf-nsight-compute-analysis

Installed? Explore more Développement et programmation skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Analyse Nsight Compute

NVIDIA Nsight Compute (ncu) profile des kernels CUDA individuels pour déterminer pourquoi ils sont lents et quoi optimiser. Il mesure le débit du GPU en pourcentage du pic théorique (Speed of Light / SOL%), permettant une classification systématique des goulots d'étranglement et une optimisation ciblée.

Quand l'utiliser

Utilisez ce skill lorsque vous rencontrez :

  • Déclencheurs : L'utilisateur souhaite profiler un kernel CUDA, analyser la sortie ncu, interpréter des rapports .ncu-rep ou optimiser les performances d'un kernel GPU
  • Symptômes : Kernel s'exécutant plus lentement que prévu, faible utilisation du GPU, besoin de classer compute-bound vs memory-bound, problèmes d'occupation
  • Mots-clés : "ncu", "nsight compute", "SOL%", "speed of light", "kernel profiling", "compute-bound", "memory-bound", "latency-bound", "occupancy", "roofline", "warp stalls", "cache hit rate", "ncu-rep"

N'utilisez PAS ce skill pour :

  • Le profilage au niveau système (utilisez Nsight Systems / nsys à la place)
  • Le traçage d'API CUDA ou l'analyse de chronologie CPU-GPU (utilisez nsys)
  • La surveillance GPU sans profilage (utilisez nvidia-smi)

Prérequis

DépendanceVersionNotes
CUDA Toolkit>=11.0Inclut ncu
Binaire ncuSupporté par le driverNsight Compute 2026.3 nécessite un driver compatible avec CUDA 13. Ou définir la variable d'env $NCU
GPU NVIDIATuring+Volta nécessite Nsight Compute 2025.2 ou plus ancien

Permissions : ncu peut nécessiter sudo, CAP_SYS_ADMIN, ou --privileged dans les conteneurs. ncu -v affiche uniquement la version ; l'absence de permission apparaît comme ERR_NVGPUCTRPERM lorsque le premier kernel est profilé.

Principes

Intégrité des données

Il s'agit d'un système d'analyse basé sur les données. Chaque nombre présenté doit avoir une source faisant autorité. Suivez ces règles sans exception :

  1. Citez avant d'interpréter. Lors de la présentation de métriques issues de la sortie ncu, montrez toujours la commande ncu réelle que vous avez exécutée ET la sortie brute pertinente (lignes CSV, valeurs de métriques) avant d'énoncer une conclusion numérique.
  2. N'inventez jamais de métriques. Si ncu échoue, retourne une sortie inattendue, ou vous ne pouvez pas l'exécuter, dites-le explicitement. N'inventez pas de nombres plausibles. Un honnête "le profilage a échoué" est mieux que des données fabriquées.
  3. Attribuez chaque valeur. Pour chaque métrique que vous citez (SOL%, durée, occupation, débit), le lecteur doit pouvoir la retracer jusqu'à une ligne spécifique dans la sortie brute ncu que vous avez montrée.

Modèle mental SOL%

Speed of Light (SOL%) mesure à quel point un kernel s'approche du pic théorique du GPU :

  • SOL% Compute (Compute (SM) Throughput) = débit de l'unité SM la plus occupée en % de son pic
  • SOL% Mémoire (Memory Throughput) = débit de l'unité mémoire la plus occupée (DRAM, L2, L1, mémoire partagée) en % de son pic

La métrique la plus élevée révèle généralement le type de goulot d'étranglement. Utilisez-la comme signal de classification principal. Les deux peuvent être élevés en même temps : le kernel est alors proche de la limite matérielle pour son algorithme.

Seuils de classification

Compute %Memory %Goulot d'étranglementProchaine étape
>60<40Compute-boundSection ComputeWorkloadAnalysis
<40>60Memory-boundSection MemoryWorkloadAnalysis
<40<40Latency-boundSections LaunchStats + Occupancy
40-6040-60ÉquilibréProfiler plus profondément avec les sections détaillées
>60>60Proche des limites matériellesChangement algorithmique ; vérifier les deux sections de charge de travail

Signaux supplémentaires :

  • Durée <10us avec de nombreux lancements -> Limité par le surcoût de lancement (utiliser d'abord nsys)
  • Les deux <40% mais occupation >50% -> Limité par les instructions (vérifier InstructionStats)

Niveaux de performance SOL%

SOL%NiveauAction
>80%ExcellentAjustements mineurs uniquement
60-80%BonOptimisation ciblée
40-60%CorrectOptimisation significative nécessaire
<40%MédiocreRefonte majeure nécessaire

Profilage par section

Utilisez toujours des drapeaux --section ciblés au lieu de la collecte en bloc --set. Les sections individuelles sont plus rapides et plus chirurgicales. Ne passez à --set basic ou --set detailed que lorsqu'une exploration large est nécessaire.

ncu vs nsys

OutilPortéeSurchargeObjectif
nsysAu niveau système5-10%Trouver quels kernels optimiser
ncuAu niveau kernel10-100x plus lentComprendre pourquoi un kernel est lent

Utilisez d'abord nsys pour identifier les principaux kernels en temps GPU, puis ncu pour une analyse approfondie de ces kernels spécifiques.

Workflow

Choisissez votre chemin en fonction de la demande :

  • Requête de connaissance (quelles métriques utiliser, --section vs --set, comment filtrer les kernels) : Répondez directement à partir des Principes, de la Référence des commandes et des Références ci-dessous. N'exécutez PAS ncu.
  • Diagnostic rapide (classer le goulot d'étranglement, vérifier SOL%) : Étape 1 uniquement. Approfondissez si l'utilisateur le souhaite.
  • Diagnostic spécifique (conflits de banques, pression de registres, occupation) : Vérification rapide SOL% (Étape 1), puis allez directement à la section pertinente à l'Étape 2.
  • Analyse approfondie (rapport détaillé, recommandations d'optimisation) : Étapes complètes 1 à 5. Présentez le rapport structuré complet avec toutes les métriques clés (SOL%, durée, occupation) dans votre réponse finale — ne répartissez pas le rapport sur plusieurs messages et ne le remplacez pas par un bref résumé.

Étape 0 : Vérifier ncu

ncu -v
# Ou : $NCU -v

S'il n'est pas trouvé, assurez-vous que le toolkit CUDA est installé ou définissez la variable d'env NCU sur le chemin du binaire.

Étape 1 : Diagnostic SOL%

Commencez toujours par SpeedOfLight pour classer le goulot d'étranglement :

ncu --section SpeedOfLight --csv \
    --kernel-name regex:"KERNEL" \
    --launch-skip 5 --launch-count 3 \
    -- COMMAND

Lisez Compute (SM) Throughput et Memory Throughput dans la sortie. Classez en utilisant les seuils ci-dessus.

Étape 2 : Approfondir avec des sections ciblées

En fonction de la classification de l'Étape 1, ajoutez des sections :

ClassificationSections à ajouter
Compute-boundComputeWorkloadAnalysis
Memory-boundMemoryWorkloadAnalysis
Latency-boundLaunchStats, Occupancy
Warp stallsWarpStateStats, SchedulerStats
Détail d'instructions nécessaireInstructionStats

Incluez toujours LaunchStats et Occupancy lors du diagnostic des kernels latency-bound. Ceux-ci révèlent la pression de registres, les limites de mémoire partagée et les problèmes de taille de bloc.

Exemple -- plongée approfondie memory-bound :

ncu --section SpeedOfLight --section MemoryWorkloadAnalysis --csv \
    --kernel-name regex:"embedding_lookup" \
    --launch-count 3 \
    -- python script.py

Exemple -- plongée approfondie compute-bound :

ncu --section SpeedOfLight --section ComputeWorkloadAnalysis --csv \
    --kernel-name regex:"gemm|nvjet" \
    --launch-count 3 -- python script.py

Exemple -- enquête sur l'occupation :

ncu --section SpeedOfLight --section LaunchStats --section Occupancy --csv \
    --kernel-name regex:"small_kernel" \
    -- python script.py

Étape 3 : Analyse Roofline (Optionnelle)

Pour une compréhension visuelle de l'équilibre compute vs mémoire. Les sections roofline sont des graphiques : sur le CLI, ils s'impriment uniquement avec --print-details all, ce qui liste les nombres derrière le graphique (travail et trafic atteints et pics). Pour voir le graphique, enregistrez un rapport avec -o et ouvrez-le dans l'interface Nsight Compute.

ncu --section SpeedOfLight_RooflineChart --print-details all \
    --kernel-name regex:"KERNEL" -- COMMAND

Pour un roofline hiérarchique spécifique à la précision :

# Kernels FP16
ncu --section SpeedOfLight_HierarchicalHalfRooflineChart --print-details all \
    --kernel-name regex:"KERNEL" -- COMMAND

# Kernels Tensor core
ncu --section SpeedOfLight_HierarchicalTensorRooflineChart --print-details all \
    --kernel-name regex:"KERNEL" -- COMMAND

Interprétation : un kernel à gauche du point de crête = memory-bound ; à droite = compute-bound ; loin sous les deux toits = problème de latence/occupation. Voir references/roofline-analysis.md.

Étape 4 : Interpréter et Optimiser

  1. Identifiez le goulot d'étranglement dominant à partir de la classification SOL%
  2. Consultez l'analyse détaillée et les stratégies d'optimisation dans references/bottleneck-guide.md
  3. Appliquez d'abord l'optimisation au plus fort impact
  4. Re-profilez pour valider l'amélioration et détecter les changements de goulot d'étranglement

Étape 5 : Valider

Re-profilez le même kernel après optimisation :

ncu --section SpeedOfLight --csv \
    --kernel-name regex:"optimized_kernel" \
    --launch-count 3 \
    -- python optimized_script.py

Comparez : Le pourcentage de débit a-t-il augmenté ? La durée a-t-elle diminué ? Le type de goulot d'étranglement a-t-il changé ?

Profilage de Kernels Compilés JIT (Triton/cuTile/CuTeDSL)

Les kernels compilés JIT déclenchent un auto-réglage lors du premier appel. Isolez l'exécution réelle :

  1. Échauffez d'abord : Exécutez le kernel 3 à 5 fois pour terminer la compilation JIT et l'auto-réglage, puis torch.cuda.synchronize().
  2. Utilisez des marqueurs de profileur : Encadrez la région mesurée avec cudaProfilerStart()/cudaProfilerStop().
  3. Utilisez --profile-from-start off pour que ncu ne capture que la région marquée :
# Échauffement (JIT + auto-réglage)
for _ in range(5):
    result = kernel(inputs)
torch.cuda.synchronize()

# Profilage de l'état d'équilibre uniquement
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

Alternative : utilisez --launch-skip N pour sauter les lancements d'auto-réglage. Voir references/advanced-profiling.md pour les alternatives avec plage NVTX et mode de rejeu.

Analyse Programmatique des Rapports

Extrayez des métriques à partir de fichiers .ncu-rep ou .ncu-repz en utilisant le module Python ncu_report (dans extras/python/ de l'installation 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()
        # SpeedOfLight : "Compute (SM) Throughput" et "Memory Throughput"
        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 = "compute-bound"
        elif memory > 60:
            classification = "memory-bound"
        else:
            classification = "latency-bound"

        print(f"{name}: {classification} (compute={compute:.1f}%, mem={memory:.1f}%, {duration}ns)")

Voir references/python-report-api.md pour l'API complète (classes IContext, IRange, IAction, IMetric).

Formats de sortie

Sortie CSV (pour les scripts et l'analyse automatisée) :

ncu --csv --section SpeedOfLight --kernel-name regex:"KERNEL" -- COMMAND
ncu --csv --page raw --section SpeedOfLight -- COMMAND   # Toutes les métriques à plat

Le CSV par défaut a une ligne par métrique. Ses colonnes incluent ID (le lancement profilé), Kernel Name, Section Name, Metric Name, Metric Unit et Metric Value ; les résultats de règle sont des lignes qui remplissent Rule Name, Rule Description et Estimated Speedup. Un Metric Name peut se répéter entre les sections (Memory Throughput est % dans SpeedOfLight et byte/s dans MemoryWorkloadAnalysis), donc filtrez aussi sur Section Name. --page raw donne une ligne par lancement, une colonne par métrique, et une deuxième ligne d'unités. Les valeurs sont en unités de base (ns, hz, %).

Pendant le profilage, les lignes ==PROF== de ncu et la sortie propre de l'application partagent stdout avec le CSV. Pour un CSV propre, écrivez un rapport et relisez-le :

Fichiers de rapport (pour analyse ultérieure) :

ncu -o report.ncu-rep --section SpeedOfLight -- COMMAND
ncu --import report.ncu-rep --csv                       # Une ligne par métrique
ncu --import report.ncu-rep --csv --page raw            # Une ligne par lancement

Donnez à -o l'extension : sans extension, Nsight Compute 2026.3 et plus récent écrivent le report.ncu-repz compressé en zstd, et les versions plus anciennes écrivent report.ncu-rep. --import et ncu_report lisent les deux.

Lignes de métriques clés (valeurs Metric Name) :

Metric NameSectionSignification
DurationSpeedOfLightTemps d'exécution
Compute (SM) ThroughputSpeedOfLight% du pic de calcul
Memory ThroughputSpeedOfLight% du pic de l'unité mémoire la plus occupée
SM FrequencySpeedOfLightHorloge à laquelle le profil a été exécuté
Achieved OccupancyOccupancyWarps actifs / warps max (%)

Indicateurs de succès :

  • Valeurs SOL% présentes dans la sortie -> profilage réussi
  • Valeurs de durée raisonnables (pas 0 ou extrêmement grandes)
  • Plusieurs lancements capturés lorsque --launch-count > 1

Exemples

Exemple : Classer un Kernel GEMM

Les kernels cuBLAS GEMM sur Blackwell sont nommés nvjet_*, donc faites correspondre les deux noms :

ncu --section SpeedOfLight --csv \
    --kernel-name regex:"gemm|nvjet" \
    --launch-skip 5 --launch-count 3 \
    -- python train.py

Sortie pour un matmul FP16 4096x4096 sur B200 (colonnes et lignes abrégées) :

"ID",...,"Kernel Name",...,"Section Name","Metric Name","Metric Unit","Metric Value",...
"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",

Interprétation : compute-bound (77.1% compute, 38.4% mémoire). Prochaine étape : vérifier l'utilisation du tensor core avec --section ComputeWorkloadAnalysis.

Exemple : Diagnostiquer un Kernel d'Embedding Memory-Bound

PyTorch embedding lookup exécute vectorized_gather_kernel, donc faites-le correspondre aussi :

ncu --section SpeedOfLight --section MemoryWorkloadAnalysis --csv \
    --kernel-name regex:"gather|index|embedding" \
    --launch-count 3 -- python train.py

Vérifiez les taux de succès du cache L1/L2 dans la sortie : des taux faibles suggèrent une bande passante mémoire DRAM élevée. Voir references/bottleneck-guide.md pour les stratégies.

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

Skills associés