aoti-debug

Par pytorch · pytorch

Déboguez les erreurs et plantages AOTInductor (AOTI). À utiliser en cas de segfaults AOTI, d'erreurs de mismatch de device, d'échecs de chargement de constantes, ou d'erreurs runtime provenant de `aot_compile`, `aot_load`, `aoti_compile_and_package` ou `aoti_load_package`.

npx skills add https://github.com/pytorch/pytorch --skill aoti-debug

Guide de Débogage AOTI

Cette skill aide à diagnostiquer et corriger les problèmes courants d'AOTInductor.

Routage par Motif d'Erreur

Vérifiez le message d'erreur et routez vers le sous-guide approprié :

Triton Index Out of Bounds

Si l'erreur correspond à ce motif :

Assertion `index out of bounds: 0 <= tmpN < ksM` failed

→ Suivez le guide dans triton-index-out-of-bounds.md

Toutes les Autres Erreurs

Continuez avec les sections ci-dessous.


Première Étape : Toujours Vérifier l'Appareil et la Concordance des Formes

Pour TOUTE erreur AOTI (segfault, exception, crash, sortie incorrecte), TOUJOURS vérifier ceci en premier :

  1. Device de compilation == Device de chargement : Le modèle doit être chargé sur le même type d'appareil que celui sur lequel il a été compilé
  2. Les appareils d'entrée correspondent : Les entrées d'exécution doivent être sur le même appareil que le modèle compilé
  3. Les formes d'entrée correspondent : Les formes d'entrée d'exécution doivent correspondre aux formes utilisées lors de la compilation (ou satisfaire les contraintes de formes dynamiques)
# Pendant la compilation - notez l'appareil et les formes
model = MyModel().eval()           # Quel appareil ? CPU ou .cuda() ?
inp = torch.randn(2, 10)           # Quel appareil ? Quelle forme ?
compiled_so = torch._inductor.aot_compile(model, (inp,))

# Pendant le chargement - le type d'appareil DOIT correspondre à la compilation
loaded = torch._export.aot_load(compiled_so, "???")  # Doit correspondre au device modèle/entrée ci-dessus

# Pendant l'inférence - l'appareil et les formes DOIVENT correspondre
out = loaded(inp.to("???"))  # Doit correspondre au device de compilation, la forme doit correspondre

Si l'un de ceux-ci ne correspond pas, vous obtiendrez des erreurs allant des segfaults aux exceptions en passant par les sorties incorrectes.

Contrainte Clé : Correspondance du Type d'Appareil

AOTI exige que la compilation et le chargement utilisent le même type d'appareil.

  • Si vous compilez sur CUDA, vous devez charger sur CUDA (l'index du device peut différer)
  • Si vous compilez sur CPU, vous devez charger sur CPU
  • Le chargement entre appareils (par exemple, compiler sur GPU, charger sur CPU) N'EST PAS pris en charge

Motifs d'Erreurs Courants

1. Segfault de Désadéquation d'Appareil

Symptôme : Segfault, exception, ou crash pendant aot_load() ou l'exécution du modèle.

Exemples de messages d'erreur :

  • The specified pointer resides on host memory and is not registered with any CUDA device
  • Crash lors du chargement des constantes dans AOTInductorModelBase
  • Expected out tensor to have device cuda:0, but got cpu instead

Cause : Les types d'appareil de compilation et de chargement ne correspondent pas (voir « Première Étape » ci-dessus).

Solution : Assurez-vous que la compilation et le chargement utilisent le même type d'appareil. Si compilé sur CPU, chargez sur CPU. Si compilé sur CUDA, chargez sur CUDA.

2. Désadéquation d'Appareil d'Entrée à l'Exécution

Symptôme : RuntimeError lors de l'exécution du modèle.

Cause : L'appareil d'entrée ne correspond pas à l'appareil de compilation (voir « Première Étape » ci-dessus).

Meilleur Débogage : Exécutez avec AOTI_RUNTIME_CHECK_INPUTS=1 pour des erreurs plus claires. Cet indicateur valide toutes les propriétés d'entrée, y compris le type d'appareil, le dtype, les tailles et les foulées :

AOTI_RUNTIME_CHECK_INPUTS=1 python your_script.py

Cela produit des messages d'erreur exploitables comme :

Error: input_handles[0]: unmatched device type, expected: 0(cpu), but got: 1(cuda)

Débogage des Erreurs CUDA Illegal Memory Access (IMA)

Si vous rencontrez des erreurs CUDA illegal memory access, suivez cette approche systématique :

Étape 1 : Vérifications de Santé

Avant d'approfondir, essayez ces indicateurs de débogage :

AOTI_RUNTIME_CHECK_INPUTS=1
TORCHINDUCTOR_NAN_ASSERTS=1

Ces indicateurs prennent effet au moment de la compilation (au moment du codegen) :

  • AOTI_RUNTIME_CHECK_INPUTS=1 vérifie que les entrées satisfont les mêmes gardes utilisées lors de la compilation
  • TORCHINDUCTOR_NAN_ASSERTS=1 ajoute du codegen avant et après chaque kernel pour vérifier les NaN

Étape 2 : Localiser l'IMA CUDA

Les erreurs IMA CUDA peuvent être non-déterministes. Utilisez ces indicateurs pour déclencher l'erreur de manière déterministe :

PYTORCH_NO_CUDA_MEMORY_CACHING=1
CUDA_LAUNCH_BLOCKING=1

Ces indicateurs prennent effet à l'exécution :

  • PYTORCH_NO_CUDA_MEMORY_CACHING=1 désactive l'allocateur de cache de PyTorch, qui alloue des buffers plus grands que nécessaire immédiatement. C'est généralement pourquoi les erreurs IMA CUDA sont non-déterministes.
  • CUDA_LAUNCH_BLOCKING=1 force les kernels à se lancer un à la fois. Sans cela, vous obtenez des avertissements « CUDA kernel errors might be asynchronously reported » puisque les kernels se lancent de manière asynchrone.

Étape 3 : Identifier les Kernels Problématiques avec le Débogueur de Valeurs Intermédiaires

Utilisez le Débogueur de Valeurs Intermédiaires AOTI pour localiser le kernel problématique :

AOT_INDUCTOR_DEBUG_INTERMEDIATE_VALUE_PRINTER=3

Cela affiche les kernels un par un à l'exécution. Combiné aux indicateurs précédents, cela montre quel kernel a été lancé juste avant l'erreur.

Pour inspecter les entrées d'un kernel spécifique :

AOT_INDUCTOR_FILTERED_KERNELS_TO_PRINT="triton_poi_fused_add_ge_logical_and_logical_or_lt_231,_add_position_embeddings_kernel_5" AOT_INDUCTOR_DEBUG_INTERMEDIATE_VALUE_PRINTER=2

Si les entrées du kernel sont inattendues, inspectez le kernel qui produit la mauvaise entrée.

Outils de Débogage Supplémentaires

Journalisation et Traçage

  • tlparse / TORCH_TRACE : Fournit les codes de sortie complets et enregistre les gardes utilisées
  • TORCH_LOGS : Utilisez TORCH_LOGS="+inductor,output_code" pour voir plus de logs internes PT2
  • TORCH_SHOW_CPP_STACKTRACES : Définissez à 1 pour voir plus de traces de pile

Sources Courantes de Problèmes

  • Formes dynamiques : Historiquement une source de nombreuses IMA. Accordez une attention particulière lors du débogage de scénarios de formes dynamiques.
  • Opérations personnalisées : Notamment quand implémentées en C++ avec formes dynamiques. La fonction meta peut avoir besoin d'être « Symint'ifiée ».

Notes API

API Dépréciée

torch._export.aot_compile()  # Dépréciée
torch._export.aot_load()     # Dépréciée

API Actuelle

torch._inductor.aoti_compile_and_package()
torch._inductor.aoti_load_package()

La nouvelle API stocke les métadonnées d'appareil dans le package, donc aoti_load_package() utilise automatiquement le type d'appareil correct. Vous pouvez uniquement changer l'index de l'appareil (par exemple, cuda:0 vs cuda:1), pas le type d'appareil.

Résumé des Variables d'Environnement

Variable Quand Objectif
AOTI_RUNTIME_CHECK_INPUTS=1 Temps de compilation Valider que les entrées correspondent aux gardes de compilation
TORCHINDUCTOR_NAN_ASSERTS=1 Temps de compilation Vérifier les NaN avant/après les kernels
PYTORCH_NO_CUDA_MEMORY_CACHING=1 Exécution Rendre les erreurs IMA déterministes
CUDA_LAUNCH_BLOCKING=1 Exécution Forcer les lancements de kernels synchrones
AOT_INDUCTOR_DEBUG_INTERMEDIATE_VALUE_PRINTER=3 Temps de compilation Afficher les kernels à l'exécution
TORCH_LOGS="+inductor,output_code" Exécution Voir les logs internes PT2
TORCH_SHOW_CPP_STACKTRACES=1 Exécution Afficher les traces de pile C++

Skills similaires