Ces deux derniers jours, j'ai passé mon temps à analyser des graphiques de profils de mémoire GPU. Comme il existe peu d'informations sur l'interprétation de ces profils, j'ai écrit un script pour le faire en une seule ligne et j'ai rédigé un article de blog à ce sujet. Que signifient toutes ces formes étranges ? Tutoriel rapide🧵
Pour profiler un bloc de code, il suffit de déposer ce fichier Python dans votre projet et d'utiliser un code similaire à celui github.com/sytelus/nanugp… les données de profilage : https://t.co/iYTzEFksVR
Vous obtiendrez une visualisation similaire à celle ci-dessous. Vous pouvez immédiatement observer 3 motifs répétitifs correspondant aux 3 étapes d'entraînement. C'est un bon début. Ces bandes indiquent les opérations de mémoire effectuées couche par couche. La bande constante en dessous représente les paramètres du modèle et l'état de l'optimiseur. Mais que sont toutes ces choses ?
Commençons par la première étape d'entraînement et analysons-la. Elle débute par un demi-triangle, qui correspond à la passe avant. Elle se termine par la création des logits, représentée par un grand parallélogramme rouge. Le pic initial correspond à la mémoire temporaire pour la fonction softmax. La taille importante des logits s'explique par le fait que le vocabulaire contient 151 000 mots.
Ensuite, nous appelons zero_grad(), ce qui efface les anciennes allocations de .grad. À la fin de zero_grad(), on observe un léger pic suivi d'une chute brutale. Le pic correspond au début de .backward() à l'étape softmax, et la chute brutale est due au fait que le tenseur logits n'est plus nécessaire. Ceci produit les gradients de tête du modèle de langage (bande verte).
Sur l'image ci-dessus, remarquez le motif ondulé à droite. Il est dû à l'activation du point de contrôle d'activation. Chaque couche est alors recalculée, ce qui provoque de petits pics, et son tenseur d'entrée est libéré à mesure que la méthode `.backward()` progresse couche par couche.
Enfin, ma partie préférée : optimizer.step(). C’est tout simplement magnifique, comme un temple avec un mât. Il repose sur deux fondations. La bande orange est en fait un dégradé de calque intégré, produit par la fin de .backward().
Sur l'image ci-dessus, la bande verte représente l'espace de stockage nécessaire pour contenir la racine carrée du gradient au carré pour Adam. L'algorithme Adam fusionné calcule les mises à jour à appliquer couche par couche, ce qui explique les bandes. Au sommet, ces mises à jour sont appliquées en une seule fois. Le pic correspond à la mémoire tampon temporaire nécessaire à la division avant l'application de la mise à jour.
Il y a encore beaucoup à dire sur ces magnifiques visualisations. N'hésitez pas à me signaler toute erreur ou autre information intéressante. Plus d'infos sur mon blog : Comment obtenir et inteshital.com/blog/gpu-memor… la mémoire GPU https://t.co/3uPt0S6RIp





