Résoudre les problèmes liés à TensorFlow – TPU
Ce guide, ainsi que les questions fréquentes, fournissent des conseils de dépannage aux utilisateurs qui entraînent des modèles TensorFlow sur Cloud TPU. Si vous dépannez un entraînement Pytorch ou JAX, vous pouvez vous reporter aux documents de dépannage correspondant à ces frameworks:
Pour accéder à des guides plus généraux sur l'utilisation de Cloud TPU, consultez les pages suivantes:
- Utiliser le colab TPU
- Guides de démarrage rapide pour Cloud TPU
- Tutoriel MNIST
- Entraîner des modèles de ML sur des TPU (Tensor Processing Units)
Présentation
Les problèmes courants rencontrés avec les Cloud TPU appartiennent aux catégories suivantes :
Problèmes de connexion au serveur TPU
Cette section explique comment résoudre les problèmes dans lesquels TensorFlow cesse de répondre ou affiche une erreur lors de la connexion au TPU. L'étape de compilation du graphe TPU peut prendre beaucoup de temps pour les modèles volumineux. Laissez le script s'exécuter pendant au moins cinq minutes avant de conclure qu'il a cessé de répondre.
La première étape consiste à vérifier si le problème concerne le serveur lui-même ou votre pipeline d'entraînement TensorFlow. Pour ce faire, exécutez le tutoriel MNIST en utilisant l’URL de votre serveur TPU et vérifiez qu’il fonctionne correctement. S'il y a toujours des problèmes de connexion avec le tutoriel MNIST, cela confirme que le problème est lié au serveur TPU. Dans ce cas :
Exécutez la commande suivante pour obtenir la liste des TPU disponibles. Remplacez zone et project-id par votre zone et votre ID de projet.
(vm)$ gcloud compute tpus list --zone zone --project project-id
Cela permet d'afficher des messages de sortie tels que :
NAME ZONE ACCELERATOR_TYPE NETWORK_ENDPOINT NETWORK RANGE STATUS demo-tpu us-central1-b v2-8 10.240.1.2:8470 default 10.240.1.0 READY
Vérifiez que vous transmettez la valeur correcte à
--tpu
(demo-tpu
dans l'exemple ci-dessus) et que ce TPU est classé en tant queREADY
.Si votre TPU n'est pas répertorié comme étant
READY
ou si vous avez encore des difficultés de connexion, redémarrez le serveur manuellement à l'aide de cette commande :(vm)$ gcloud compute tpus stop $TPU_SERVER_NAME && gcloud compute tpus start $TPU_SERVER_NAME
Dans l'exemple ci-dessus,
$TPU_SERVER_NAME
correspond àdemo-tpu
. Cette opération peut prendre plusieurs minutes.Exécutez à nouveau la commande
... tpus list
ci-dessus et attendez que le TPU soit dans un étatREADY
. Cela peut prendre quelques minutes.Essayez de relancer le tutoriel MNIST.
Si vous ne parvenez toujours pas à exécuter le tutoriel MNIST, demandez de l'aide via l'un des mécanismes décrits dans la section Obtenir de l'aide.
Si l'exemple MNIST fonctionne correctement, mais que votre modèle cesse toujours de répondre, le problème vient probablement de votre pipeline d'entraînement.
Pour résoudre ce problème, commencez par remplacer TPUStrategy dans votre code par la stratégie par défaut. Lorsque vous utilisez la stratégie par défaut, partout où vous utilisez strategy.scope()
ou strategy.run()
, le modèle s'exécute sur le processeur (ou sur le GPU, le cas échéant) plutôt que sur le TPU. Si le modèle s'exécute sur le processeur et non sur le TPU, il doit y avoir un problème spécifique à TPU. S'il ne s'exécute toujours pas, il est recommandé de déboguer le problème sur le processeur.
Perte de connexion ssh
pendant l'entraînement
Votre connexion ssh
à Cloud TPU peut expirer lors d'un entraînement de longue durée (en particulier si vous utilisez Cloud Shell).
À ce stade, il n'y a pas de sortie dans la console TPU et il peut sembler que le TPU a arrêté l'entraînement. Pour éviter cela, exécutez la session d'entraînement avec un multiplexeur de terminaux ou un outil de gestion de sessions tel que tmux
ou screen
. La connexion ssh
restera active quelle que soit la durée de l'entraînement.
Déboguer les erreurs courantes
Impossible de créer un TPU
Lorsque vous créez un Cloud TPU, l'erreur suivante peut s'afficher:
googleapiclient.errors.HttpError: < HttpError 403 when requesting https://content-tpu.googleapis.com/v1/projects/{PROJECT}/locations/{ZONE}/nodes/{TPU_NAME}?alt=json returned "Request had insufficient authentication scopes."
Il s'agit d'un problème d'autorisation qui peut être résolu en exécutant la commande suivante:
gcloud auth login --update-adc
Cette commande met à jour les identifiants par défaut de votre application (ADC) et devrait résoudre le problème. Pour en savoir plus, consultez la page gcloud auth connexion.
Impossible d'utiliser le système de fichiers local
Message d'erreur
InvalidArgumentError: Unimplemented: File system scheme '[local]' not implemented
Framework et configurations concernés
Ce message peut s'afficher lors de l'entraînement avec TensorFlow à l'aide de l'architecture de nœud TPU.
Détails
Tous les fichiers d'entrée et le répertoire de modèles doivent utiliser un chemin d'accès au bucket Cloud Storage (gs://bucket-name/...
). Ce bucket doit être accessible depuis le serveur TPU. Notez que l'intégralité du traitement des données et de la gestion des points de contrôle du modèle sont réalisés sur le serveur TPU et non sur la machine locale. Pour plus d'informations sur la configuration adéquate de Cloud Storage pour une utilisation avec Cloud TPU, reportez-vous au guide Se connecter aux buckets Cloud Storage.
Type de données non compatible
Message d'erreur
TypeError: DataType is not a supported TPU infeed type.
Framework et configurations concernés
Ce message peut s'afficher lors de l'entraînement avec TensorFlow à l'aide de l'architecture de nœud TPU.
Détails
Actuellement, seuls les types de données tf.float32
, tf.int32
, tf.bfloat16
et tf.bool
sont acceptés sur le TPU. Les autres types de données courants, tels que tf.uint8
, tf.string
et tf.int64
, doivent être convertis dans l'un des types compatibles lors du prétraitement des données (c'est-à-dire dans le pipeline tf.data.Dataset).
Consultez un exemple de conversion dans la fonction decode_image
utilisée dans l'entraînement MNIST.
Formes dynamiques non compatibles
Message d'erreur
ValueError: shape [Shape] must have a fixed size for dimension d that is known at graph construction time.
Framework et configurations concernés
Ce message n'apparaît que lors de la compilation XLA avec TensorFlow.
Détails
Pour exécuter un modèle sur le TPU, TensorFlow le compile à l'aide du compilateur XLA. Bien que cette étape de compilation améliore considérablement la vitesse d'entraînement et l'utilisation de la mémoire, les formes (tailles des dimensions) de tous les Tensors du graphe doivent être connues au moment de la compilation du graphe. Si la moindre forme ne peut pas être déterminée au moment de la compilation, la compilation TPU échoue avec le message d'erreur ci-dessus.
dataset.batch(batch_size)
est une opération courante qui renvoie une forme dynamique, car le nombre d'échantillons restant dans un flux peut être inférieur à la taille de lot. Par conséquent, lors de l'entraînement sur le TPU, définissez drop remainder=True
pour dataset.batch
.
Cette opération permet de supprimer les derniers échantillons d'un fichier pour garantir que chaque lot présente une forme statique de taille "batch_size". Exemple :
dataset = tf.data.Dataset.range(8)
dataset = dataset.batch(3, drop_remainder=True)
Opération TensorFlow non disponible
Message d'erreur
NotFoundError: No registered 'OpName' OpKernel for XLA_TPU_JIT devices compatible with node
Framework et configurations concernés
Ce message peut s'afficher lors de l'entraînement avec TensorFlow.
Détails
Le modèle utilise une opération TensorFlow qui n’est pas disponible pour le moment sur TPU.
Pour obtenir la liste des opérations disponibles sur TPU, ainsi que les opérations dont la compatibilité est prévue à l'avenir et les solutions de contournement, veuillez consulter le guide des opérations TensorFlow disponibles.
Message d'erreur de mémoire insuffisante
Message d'erreur
ResourceExhaustedError: Ran out of memory in memory space hbm; used: YYY; limit: 7.48G.
Framework et configurations concernés
Ce message peut s'afficher lors de l'entraînement avec TensorFlow, PyTorch ou JAX.
Détails
Chaque Cloud TPU est composé de huit cœurs de TPU, les TPU v2 disposent de 8 Go et les TPU v3 ont 16 Go de RAM (ou HBM, pour la mémoire à haut débit). Cette mémoire est utilisée pour stocker les Tensors des pondérations (variables), ainsi que les Tensors des résultats intermédiaires nécessaires aux calculs de gradients. Si le modèle est trop volumineux pour tenir dans la mémoire RAM du TPU, l'initialisation échoue et le message d'erreur ci-dessus est affiché. Consultez la section Réduire l'utilisation de la mémoire pour obtenir de l'aide.
Conseils pour réduire l'utilisation de la mémoire:
- Recherchez une remplissage excessif du tenseur.
- Utilisez le format bfloat16.
- Si les tailles ou le modèle d'entrée sont trop volumineux, vous pouvez peut-être utiliser le parallélisme de modèle expérimental de TensorFlow pour remédier à la taille du modèle.
Problèmes d'arrêt de l'exécution
Si TensorFlow rencontre une erreur lors de l'exécution sur TPU, le script semble parfois cesser de répondre plutôt que quitter l'interface système. Si cela se produit, appuyez sur la combinaison de touches CTRL+\
sur le clavier pour déclencher un SIGQUIT
qui force la fermeture immédiate de Python.
De la même façon, la commande CTRL+C
pendant l'exécution TPU ne met pas fin immédiatement à TensorFlow, mais attend la fin de la boucle d'itération en cours pour s'arrêter proprement.
Si vous rencontrez de nouvelles erreurs lors de la reconnexion au TPU après vous être déconnectée de cette manière, réinitialisez manuellement le serveur TPU à l'aide des commandes suivantes:
gcloud compute tpus stop tpu-name --zone=zone gcloud compute tpus start tpu-name --zone=zone
où tpu-name est extrait de la première colonne affichée par la commande gcloud compute tpus list
et zone est la zone indiquée dans la deuxième colonne.
Remplissage excessif du Tensor
Cause possible du problème de mémoire
Les Tensors stockés dans la mémoire du TPU sont remplis, c'est-à-dire que le TPU arrondit les tailles des Tensors stockés en mémoire pour effectuer les calculs plus efficacement. Ce remplissage se produit de manière transparente au niveau du matériel et n'affecte pas les résultats. Toutefois, dans certains cas, le remplissage peut entraîner une augmentation significative de l'utilisation de la mémoire et du temps d'exécution.
Réduire l'utilisation de la mémoire
La couche logicielle TPU tente de disposer les Tensors en mémoire afin de maximiser l’efficacité des calculs et de minimiser le remplissage. Ce processus d’agencement de la mémoire est complexe, mais pour optimiser les résultats, le modèle doit respecter la règle empirique suivante. Pour minimiser la surcharge de mémoire et optimiser l'efficacité de calcul, l'une des conditions suivantes doit être remplie :
La taille totale du lot doit être un multiple de 64 (8 par cœur de TPU) et les dimensions des caractéristiques doivent être un multiple de 128.
ou
La taille totale du lot doit être un multiple de 1 024 (128 par cœur de TPU), et les dimensions des caractéristiques doivent être un multiple de 8.
L'efficacité maximale est atteinte avec une taille de lot de 1 024 et des dimensions de caractéristiques multiples de 128, bien que cela ne soit pas toujours possible pour tous les modèles. Par souci de clarté, "dimension de caractéristique" désigne la taille cachée d'une couche entièrement connectée ou le nombre de canaux de sortie dans une convolution. Certaines couches ne peuvent pas se conformer à cette règle, en particulier les première et dernière couches du réseau. Ce n'est pas un problème et il est attendu que la plupart des modèles nécessitent un certain remplissage.
Réduire l'utilisation de la mémoire
Si vous rencontrez une erreur de mémoire insuffisante lors de l'exécution de votre modèle sur TPU, vous devez prendre des mesures pour réduire l'utilisation de la mémoire par le modèle.
Voici les moyens les plus efficaces de réduire l'utilisation de la mémoire:
- Réduire le remplissage excessif de tenseur
- Réduire la taille de lot
Taille de lot ou modèle trop volumineux
Cause possible du problème de mémoire
Lors de l'entraînement d'un réseau de neurones sur un processeur, un GPU ou un TPU, l'utilisation de la mémoire provient de deux sources :
- L'utilisation de la mémoire est proportionnelle au nombre de pondérations dans le modèle.
- Le stockage des activations intermédiaires provenant du calcul de propagation avant et utilisées pour le calcul de la rétropropagation. L'utilisation de la mémoire est directement proportionnelle à la taille du lot, à la taille et au nombre de couches.
Par conséquent, la mémoire requise par un modèle dépend largement de la taille de lot.
La mémoire requise par un modèle dépend du nombre de couches du réseau.
L'environnement d'exécution TPU tente d'optimiser les opérateurs pour ajuster le modèle en mémoire (appelé rematérialisation, semblable à la gestion des points de contrôle de gradient), mais il n'est pas toujours en mesure de le faire.
Réduire l'utilisation de la mémoire
Réduisez lentement la taille de lot jusqu'à ce qu'elle tienne en mémoire, en vous assurant que la taille totale de lot est un multiple de 64 (la taille de lot par cœur doit être un multiple de 8). N'oubliez pas que des tailles de lot plus importantes sont plus efficaces sur TPU. Une taille de lot totale de 1 024 (128 par cœur) est généralement un bon point de départ.
Si le modèle ne peut pas être exécuté sur TPU même avec une taille de lot faible (par exemple, 64), essayez de réduire le nombre ou la taille des couches.
Améliorer la vitesse d'entraînement
Si votre modèle est capable de fonctionner correctement sur TPU, mais que la vitesse d’entraînement n'est pas aussi rapide qu'espéré, cette section décrit plusieurs moyens potentiels d’améliorer la vitesse. Consultez le Guide sur les performances pour obtenir d'autres suggestions sur l'amélioration des performances de l'entraînement.
Trop peu d'étapes par exécution et par boucle d'entraînement
Description du problème de performances
Transmettre l'argument steps_per_execution
à Model.compile
contrôle le nombre d'étapes d'entraînement exécutées entre les rappels d'hôte.
Chaque rappel d'hôte nécessite une communication importante entre le processeur hôte du serveur TPU et l'appareil TPU. Par conséquent, si la valeur de steps_per_execution
est trop petite, l'entraînement peut être ralenti.
Comment savoir si votre modèle est affecté
Si un profil TPU révèle des rappels fréquents de processeur hôtes entre les étapes de l'appareil TPU, votre entraînement peut bénéficier d'une valeur steps_per_execution
plus élevée.
Minimiser le problème
Définissez steps_per_execution
sur une valeur plus élevée. Notez que steps_per_execution
peut être défini sur une valeur élevée, mais n'oubliez pas que les messages de journalisation et l'enregistrement d'un point de contrôle ne peuvent avoir lieu qu'après l'exécution du nombre d'étapes spécifié.
Goulot d'étranglement au niveau du traitement des entrées
Description du problème de performances
Pendant que le TPU effectue l'entraînement sur un bloc de données particulier, la fonction de traitement des entrées utilise le processeur pour préparer le bloc de données suivant. Si votre fonction d'entrée prend plus de temps que la fonction de modèle, le TPU reste inactif pendant que votre fonction d'entrée récupère les données.
Comment savoir si votre modèle est affecté
Suivez les instructions de la documentation Outils Cloud TPU : analyseur du pipeline d'entrées pour afficher l’analyse du pipeline d’entrées dans TensorBoard :
La page d'analyse du pipeline d'entrées présente un résumé clair indiquant si votre modèle présente un goulot d'étranglement au niveau du traitement des entrées. La même page affiche également le temps d'exécution par opération, ce qui vous permet d'identifier les opérations problématiques.
Minimiser le problème
Il existe plusieurs solutions au niveau du chargement de données grâce à l'API Dataset
:
- Stockez vos données sous forme de collection de structures
tf.train.Example
dans des fichiersTFRecord
, et chargez-les à l'aide deTFRecordDataset
. Consultez le tutoriel sur l'API Dataset ou le tutoriel ResNet pour voir des exemples. - Utilisez
dataset.cache()
et/oudataset.prefetch()
pour mettre en mémoire tampon les données d'entrée. Cela évite que les ralentissements sporadiques au niveau de l'accès aux fichiers ne créent un goulot d'étranglement. - Spécifiez le paramètre
num_parallel_calls
de la fonctiondataset.map()
pour activer les opérations multithreadmap()
. Une heuristique simple pour la valeur denum_parallel_calls
consiste à utiliser le nombre de cœurs de processeur disponibles. - Effectuez le prétraitement coûteux des données hors ligne comme une dépense unique, plutôt que de subir les frais occasionnés à chaque époque de chaque entraînement.
L'ensemble du traitement des entrées est effectué sur les processeurs situés sur le serveur TPU, et non sur la machine locale. La vitesse de la machine locale n'est donc pas un facteur.
Temps de pas lent et faible utilisation des unités matricielles
Description du problème de performances
Cloud TPU peut effectuer des multiplications et des convolutions de matrices à des vitesses incroyablement élevées. La plupart des autres opérations TensorFlow ont des mises en œuvre efficaces sur TPU, mais elles ne représentent pas le point fort des TPU par rapport à un autre type de matériel. Par conséquent, pour tirer pleinement parti du TPU, un modèle doit reposer essentiellement sur des multiplications ou convolutions de matrices.
Comment savoir si votre modèle est affecté
Dans ce cas, les symptômes sont des ralentissements associés à une faible utilisation des MXU lorsque vous profilez les performances.
Minimiser le problème
Essayez de réduire le nombre d'opérations qui ne sont pas des multiplications matricielles. Après avoir réduit le nombre de multiplications de matrices, effectuez une nouvelle analyse comparative pour voir si les performances sont acceptables sur les TPU.
Remplissage excessif du Tensor
Description du problème de performances
Le TPU remplit les tenseurs en mémoire de manière à pouvoir utiliser efficacement ses unités de calcul. Le remplissage peut augmenter l'utilisation de la mémoire, ainsi que de la bande passante mémoire. Consultez la section sur le remplissage de Tensor pour comprendre et résoudre les problèmes de remplissage de Tensor.
Débit lent et faible utilisation de la mémoire
Description du problème de performances
En règle générale, l'utilisation de lots de grande taille accélère l'apprentissage sur TPU, en termes d'échantillons/seconde.
Comment savoir si votre modèle est affecté
La taille de lot de tout modèle doit toujours être d'au moins 64 (huit par cœur de TPU), car le TPU remplit systématiquement les Tensors pour atteindre cette taille. La taille de lot idéale pour l'apprentissage sur TPU est de 1 024 (128 par cœur de TPU), car cela élimine les inefficacités liées au transfert de mémoire et au remplissage.
Minimiser le problème
La bonne pratique consiste à utiliser la plus grande taille de lot, qui s'adapte à la mémoire et soit un multiple de 64. La méthode la plus simple consiste à démarrer à 1 024. Si cela provoque une erreur de mémoire insuffisante, essayez de réduire la taille de lot jusqu'à ce que le modèle s'exécute correctement. Modifier la taille de lot d'un modèle peut nécessiter l'ajustement d'autres hyperparamètres, tels que le taux d'apprentissage, pour obtenir la même justesse de modèle, mais cela doit être évalué au cas par cas.
La taille des couches est trop faible
Description du problème de performances
Même lorsqu'un modèle est dominé par des multiplications ou convolutions de matrices, le TPU peut ne pas fonctionner à pleine efficacité si les Tensors d'entrée sont petits. Par rapport à d'autres types de matériel, le TPU fonctionne plus efficacement lorsque les lots et les couches sont de grande taille (par exemple, de dimension >= 512).
Comment savoir si votre modèle est affecté
En règle générale, les tailles de couche inférieures à 128 n'atteignent qu'une efficacité médiocre sur TPU, car 128 est la dimension native de l'unité de multiplication matricielle TPU. Pour les couches entièrement connectées, une taille cachée minimale de 512 est recommandée pour obtenir une efficacité élevée. Notez que les couches convolutives n'ont généralement pas besoin d'être aussi grandes que des couches entièrement connectées pour atteindre un niveau d'efficacité équivalent.
Minimiser le problème
Si la principale motivation des petites tailles de couches de votre modèle est la vitesse d'entraînement, effectuez une nouvelle analyse comparative de vos modèles avec des couches plus grandes sur le TPU. Par exemple, faire passer la taille de sortie d'une couche de 256 à 512 ne peut augmenter la durée d'entraînement que de 20 %, même si le modèle effectue deux fois plus de calculs.
Profilage de modèle au niveau des opérations
Il est souvent utile de mesurer le temps d'exécution et l'utilisation de la mémoire au niveau des opérations afin d'identifier les goulots d'étranglement des performances. Pour obtenir des instructions sur la procédure à suivre,
consultez le guide Outils Cloud TPU: Lecteur de traces.
Le débogage dégrade la justesse du modèle
L’un des objectifs de l’écosystème Cloud TPU est que tout modèle actuellement entraîné sur un processeur ou un GPU atteigne une précision très similaire lorsqu’il est entraîné sur un TPU, avec éventuellement des ajustements mineurs au niveau d'hyperparamètres tels que la taille de lot et le taux d’apprentissage. Cependant, les utilisateurs peuvent parfois observer une dégradation de la justesse de certains modèles après entraînement sur un TPU. Déboguer de tels problèmes peut être extrêmement frustrant en raison de la nature aléatoire de l'entraînement des réseaux de neurones. Cette section explique comment identifier la cause première de toute dégradation de la justesse d'un modèle lors du transfert sur TPU.
Comprendre la segmentation de données (parallélisme des données)
L'un des principaux objectifs de TensorFlow est de faire en sorte que chaque opération produise des résultats quasi identiques, qu'elle soit exécutée sur processeur, GPU ou TPU. Il existe certaines exceptions à cette règle, telles que les opérations aléatoires. En général, si vous constatez une différence significative entre les résultats d'opérations non aléatoires sur TPU et sur processeur, signalez-le comme un bug.
Cependant, au niveau du pipeline d'entraînement dans son ensemble, il existe une différence significative entre l'entraînement sur le processeur/GPU et celui sur le TPU. Lors de l'entraînement sur un TPU, TensorFlow effectue une segmentation des données. Chaque Cloud TPU contient huit cœurs de TPU qui fonctionnent comme des unités de traitement indépendantes. Pour chaque étape de l'entraînement, chaque cœur de TPU reçoit un lot de données, calcule les gradients des pondérations, les échange avec les autres cœurs de TPU, puis calcule la mise à jour de la pondération. Par défaut, c'est la perte moyenne sur l'ensemble des cœurs qui est calculée, mais on peut aussi calculer la somme en modifiant le paramètre de CrossShardOptimizer
.
Si la perte totale du modèle peut être calculée comme la moyenne (ou la somme) de pertes indépendantes par échantillon, cette procédure est alors mathématiquement équivalente à un entraînement sur un seul lot de grande taille.
L'opération la plus courante qui n'est pas indépendante par échantillon est la normalisation de lot, qui s'exécute sur chaque "lot par cœur" séparément. Par exemple, si la taille de lot totale est de 128, la taille de lot par cœur est de 16 et chacun des huit cœurs réalise la normalisation du lot sur ses 16 échantillons propres. Dans certains cas, une dégradation de la justesse a été observée avec la normalisation par lot sur de petits lots (moins de 32, par exemple). Dans un scénario idéal, la taille totale des lots doit être importante (par exemple, de 256 à 1 024). Pour les lots trop volumineux pour tenir en mémoire, l’effet de la segmentation doit être évalué au cas par cas.
Entraînement déterministe
L'une des raisons pour lesquelles il est difficile de déboguer les différences de précision du modèle est que différents frameworks (TensorFlow, PyTorch, JAX) utilisent une initialisation des pondérations et un brassage des données différents à chaque entraînement d'un modèle. Il est utile de modifier la procédure d'entraînement pour qu'elle soit déterministe, afin que plusieurs exécutions produisent des modèles presque identiques. Cette section explique comment exécuter le tutoriel MNIST de manière déterministe:
- Générez un fichier de point de contrôle initial en exécutant un seul pas sur le processeur. Ce pas permet d’initialiser les pondérations de manière déterministe. Veillez également à utiliser une valeur de départ aléatoire fixe pour chaque fonction aléatoire du modèle.
# Run training for 1 step to create an initial checkpoint. python mnist_tpu.py \ --use_tpu=False \ --data_dir=${STORAGE_BUCKET}/data/ \ --model_dir=${STORAGE_BUCKET}/init_output \ --random_seed=12345 \ --iterations=1 --train_steps=1
- Modifiez les fonctions de brassage des données de votre fonction d'entrée pour utiliser une valeur de départ aléatoire. C'est déjà le cas dans le tutoriel MNIST. Cela fonctionne pour les opérations de traitement des données en entrée, car celles-ci sont toujours exécutées sur le processeur. Les opérations aléatoires dans la fonction du modèle peuvent ne pas être déterministes entre le TPU et le processeur. Chaque fois que vous appelez une opération aléatoire, transmettez une valeur de départ fixe pour obtenir les mêmes résultats entre les exécutions. Exemple :
# In the flag definitions
tf.flags.DEFINE_integer("batch_size", None, "Random seed for training")
# In the input_fn
if FLAGS.random_seed is not None:
dataset = dataset.shuffle(seed=FLAGS.random_seed)
-
Exécutez le même modèle deux fois sur le processeur pour vérifier que l'entraînement est déterministe. Notez que l'entraînement doit être exécuté pour un nombre raisonnable de pas (par exemple, 1 000), mais qu'il n'a pas besoin d'être exécuté jusqu'à la convergence.
Comme l'entraînement sur processeur est comparé à l'entraînement sur un TPU monocœur, utilisez une taille de lot pouvant tenir sur un seul cœur de TPU (généralement, la taille de lot complète divisée par huit). TensorFlow ne garantit pas un déterminisme bit par bit entre les exécutions, mais la perte doit être très proche :
Copier les pondérations initiales
gsutil mkdir ${STORAGE_BUCKET}/cpu_output_1 gsutil cp -f ${STORAGE_BUCKET}/init_output/* ${STORAGE_BUCKET}/cpu_output_1 gsutil mkdir ${STORAGE_BUCKET}/cpu_output_2 gsutil cp -f ${STORAGE_BUCKET}/init_output/* ${STORAGE_BUCKET}/cpu_output_2
Course 1
python mnist_tpu.py \ --use_tpu=False \ --data_dir=${STORAGE_BUCKET}/data/ \ --model_dir=${STORAGE_BUCKET}/cpu_output_1 \ --batch_size=128 \ --random_seed=12345 \ --train_steps=2000 \ --eval_steps=10
Sortie 1
accuracy = 0.9910644, global_step = 1000, loss = 0.025323588
Course 2
python mnist_tpu.py \ --use_tpu=False \ --data_dir=${STORAGE_BUCKET}/data/ \ --model_dir=${STORAGE_BUCKET}/cpu_output_1 \ --batch_size=128 \ --random_seed=12345 \ --train_steps=2000 \ --eval_steps=10
Sortie 2
accuracy = 0.9910644, global_step = 1000, loss = 0.025323414
Entraînement TPU monocœur
Une fois que vous pouvez exécuter le tutoriel MNIST de manière déterministe, l'étape suivante consiste à répliquer sur TPU les résultats entraînés sur le processeur, en utilisant un seul cœur de TPU pour déterminer si le problème est lié à la segmentation des données ou au moteur d'exécution du TPU lui-même.
Voici comment exécuter un entraînement et une évaluation monocœur avec le tutoriel MNIST :
Utiliser la même initialisation de pondération que le CPU
gsutil cp -f ${STORAGE_BUCKET}/init_output/* ${STORAGE_BUCKET}/tpu_output
Exécuter l'entraînement pour 1 000 pas
python mnist.py \ --use_tpu=True \ --master=$GRPC_SERVER \ --train_file=${STORAGE_BUCKET}/data/train.tfrecords \ --model_dir=${STORAGE_BUCKET}/tpu_output \ --random_seed=12345 \ --num_shards=1 \ --batch_size=128 \ --train_steps=1000 \ --eval_steps=10
Sortie
accuracy = 0.9910644, global_step = 1000, loss = 0.02514153
La perte ne correspondra pas exactement au modèle entraîné sur processeur, mais elle devrait être proche. Si ce n'est pas le cas pour votre modèle, cela peut indiquer que vous avez trouvé un bug dans le moteur d'exécution du TPU. Avant de soumettre un rapport de bug, vérifiez les points suivants :
Vous transmettez
num_shards=1
àTPUConfig
.Vous ne disposez d'aucune opération aléatoire dans votre fonction de modèle et toutes les opérations aléatoires de votre fonction d'entrée sont correctement initialisées.
Vous utilisez le même fichier de point de contrôle initial pour l'entraînement sur processeur et sur TPU.
Déboguer l'entraînement TPU multicœur
Si votre modèle atteint effectivement la même perte sur processeur et sur TPU monocœur, le problème est probablement l'un des éléments suivants :
(a) La dégradation est due à la variance aléatoire naturelle survenant lorsque l'on entraîne des modèles neuronaux avec différentes initialisations.
(b) La dégradation est due à un problème lié à la segmentation des données sur le TPU.
Pour déterminer si votre problème relève du cas (a), entraînez de nouveau le modèle complet sur processeur/GPU et sur TPU multicœur en utilisant la même initialisation des pondérations, comme ci-dessus.
Si vous êtes certain que la dégradation de la justesse est statistiquement significative, les problèmes les plus probables liés à la segmentation des données sont les suivants :
- Si votre modèle utilise la normalisation par lot, une taille de lot totale inférieure à 256 (par exemple, inférieure à 32 par cœur) peut réduire la justesse.
- Les fonctions de perte par lot sont affectées par la segmentation. Ces fonctions de perte sont généralement assez spécialisées. Par exemple Karras et al. 2017 utilisent un discriminateur par lot lors de l'entraînement d'un réseau antagoniste génératif.
Résoudre les problèmes liés aux VM TPU
Les problèmes et solutions suivants ne s'appliquent qu'aux configurations de VM TPU.
Dépannage de la configuration de gcloud
- Problème
gcloud components update
affiche le message d'erreur suivant:
ERROR: (gcloud.components.update) You cannot perform this action because the Cloud SDK component manager is disabled for this installation.
- Solution
- Pour utiliser
gcloud
avec une VM TPU, vous devez employer une installationgcloud
qui n'est pas gérée via un gestionnaire de packages. Pour installergcloud
à partir du code source, procédez comme suit:
sudo apt-get remove google-cloud-sdk curl -O https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-311.0.0-linux-x86_64.tar.gz tar -xzf google-cloud-sdk-311.0.0-linux-x86_64.tar.gz ./google-cloud-sdk/install.sh source ~/.bashrc
- Problème
La commande
gcloud compute tpus tpu-vm ssh ${TPU_NAME} --zone ${ZONE}
affiche le message d'erreur suivant :Waiting for SSH key to propagate. ssh: connect to host 34.91.136.59 port 22: Connection timed out ssh: connect to host 34.91.136.59 port 22: Connection timed out ssh: connect to host 34.91.136.59 port 22: Connection timed out ERROR: (gcloud.compute.tpus.tpu-vm.ssh) Could not SSH into the instance. It is possible that your SSH key has not propagated to the instance yet. Try running this command again. If you still cannot connect, verify that the firewall and instance are set to accept ssh traffic.
- Solution
Une erreur s'est peut-être produite lors de la propagation de la clé SSH. Déplacez les clés générées automatiquement vers un emplacement de sauvegarde pour forcer
gcloud
à les recréer :mv ~/.ssh/google_compute_engine ~/.ssh/old-google_compute_engine mv ~/.ssh/google_compute_engine.pub ~/.ssh/old-google_compute_engine.pub
Journaux de débogage
Les frameworks Cloud TPU compatibles, JAX, PyTorch et TensorFlow, accèdent aux TPU via une bibliothèque partagée appelée libtpu
, présente sur chaque VM TPU. Cette bibliothèque inclut le compilateur XLA utilisé pour compiler des programmes TPU, l'environnement d'exécution TPU utilisé pour exécuter des programmes compilés et le pilote TPU utilisé par l'environnement d'exécution pour un accès de bas niveau au TPU.
La bibliothèque libtpu
consigne des informations pouvant être utiles pour le débogage.
Par défaut, ces journaux sont écrits dans /tmp/tpu_logs
sur chaque VM Cloud TPU.
Vous pouvez définir les variables d'environnement suivantes avant de commencer l'entraînement pour modifier le comportement de journalisation:
- TPU_LOG_DIR: répertoire dans lequel les journaux sont écrits
- L'emplacement du répertoire par défaut est
/tmp/tpu_logs
. Le répertoire est créé s'il n'existe pas déjà, mais aucun répertoire parent n'est créé. Si une erreur se produit lors de la recherche ou de la création du répertoire spécifié, un message est affiché dans stderr, mais il n'interrompt pas le programme et la journalisation est désactivée. Définissez le nom du répertoire sur "désactivé" pour désactiver complètement la journalisation sur le disque. - TPU_MIN_LOG_LEVEL: gravité minimale consignée sur le disque
- Vous avez le choix entre 0 (INFO), 1 (AVERTISSEMENT), 2 (ERREUR) et 3 (FATAL). La valeur par défaut est 0.
- TPU_STDERR_LOG_LEVEL: gravité minimale consignée dans stderr, en plus du disque, le cas échéant
- Les options disponibles sont les mêmes que pour TPU_MIN_LOG_LEVEL. La valeur par défaut est 3.
- TPU_MAX_LOG_SIZE_MB: taille maximale de chaque fichier journal, en mégaoctets
- Un nouveau fichier journal est automatiquement lancé lorsque le précédent atteint à peu près cette taille. La valeur par défaut est 1 024.