L'histoire de la collection la plus complète des astuces pour améliorer le GPU

avant-propos

Tout d'abord, si vous êtes déjà familier avec tf.data estimateur +, vous pouvez prendre l'article x ╮ (¯ ▽ ¯ « ») ╭

Mais! Si maintenant ou pendant session.run (..) les mots! Particulièrement en détresse à la mémoire du GPU sont remplies, mais ne pas augmenter l'utilisation des chaussures pour enfants, cet article peut être en mesure de vous donner d'ouvrir la porte à un nouveau monde Oh (∇)

Si vous trouvez que, après une série d'amélioration de l'efficacité est grandement améliorée après la formation, souvenez-vous de revenir aux petites enveloppes du soir (∇)

Cependant, ce n'est pas un tas de pâte en colère le mot de code (c) Jane (Introduction) italien (deux) Gai (langue) à la fin des articles de style RPSC. . . Donc, tendre la main à la partie qui peut X sur ╮ (¯ ▽ ¯ « ») ╭

origine

Avant longtemps tôt le soir, quand la petite nouvelle à tensorflow et l'utilisation du GPU accéléré de calcul, un doute surgit sur. Pourquoi est presque plein de mémoire graphique, l'utilisation des GPU affiche également si bas? Bon déchets, mais ils ne font rien. Le taux d'utilisation du GPU était de 100% de la situation de base ne se trouve que dans un bourrage des tâches beaucoup plus petites 4,5 de la mémoire ne coûte pas.

Dans plus des cas extrêmes, même le taux d'utilisation du GPU sera réduite à 10% ou moins, comme ceci:

 

v2-09e10589505de7a161415b60e365e83c_b.jpg

Et après avoir écrit le train de code dans la plupart des cas, il est le suivant:

 

v2-77c8ae3aa2b468d2682c62a26f063c3c_b.jpg

On peut voir, bien que la mémoire graphique sont remplis, mais la puissance graphique (extrême gauche de la colonne, 114W et 69W) et de l'utilisation (colonne de droite de cela, 35% et 38%) est loin de la limite. La plupart des gens pensent que bien Eh bien, il n'a pas d'importance, je n'expérimenter au revoir wei [rires]

Cependant! Si vous faites expérience à grande échelle, former quelques jours pour le faire tourner? Ce détail affectera grandement l'efficacité de votre expérience et le nombre d'expériences avant l'arrivée DDL! Pensez exactement le même modèle et les paramètres, votre code devrait entraîner une semaine, mais la prochaine besoin de porte seulement former trois jours Pharaon ╮ (¯ ▽ ¯ « ») ╭

Passante: J'ai 256 cartes
petit soir: Eh bien cet article , vous pouvez X sur

Eh bien, nous pourrions ne pas avoir été cela se produise:

 

v2-fada8f09717f3847f8eae736eb0258e1_b.jpg

Est-il pas la puissance et l'efficacité semble incroyable! Ne doute est-ce que le PS figure! Ceci est juste un petit soir coups tous les jours! Une bonne utilisation des astuces d'utilisation du GPU ne tombe pas 99%, puis écrire l'oie de code assez stupide, vous pouvez aussi aller jusqu'à 5%!

La question est, quelle est la différence dans le résultat final en elle?

Ne vous inquiétez pas, nous devons regarder les gpu agrandir l'utilisation de seulement 30% des changements de code dans quelques de l'utilisation de gpu pendant la formation (il semble une phrase peu long

        watch -n 0.1 nvidia-smi
      

 

v2-06ddcf4a0187d75ce5dffbbbac13f6d2_b.gif
ps :( cadre peut tomber trop sérieux à la recherche incohérente ╮ (¯ ▽ ¯ « ») ╭, il est recommandé d'essayer sur leurs machines, sera intuitive à plusieurs ~)

Regardez! Vous ne trouverez pas tout à coup mal avec moi? Vous pouvez voir que, en fait, n'est pas l'utilisation de gpu est à un niveau relativement bas, mais rose périodique très régulière à près de 100 de 0 0 puis est tombé, puis à nouveau chuté rose par un autre 100 à 0. Si les deux ouverts à imprimer la fenêtre du journal, vous constaterez que ce cycle est exactement conforme à chaque étape de formation est longue! En d'autres termes, à chaque étape, en fait, nous avons un peu de temps et ne pas passer le GPU, bien sûr, est qu'il est passé dans le cpu.

Que le cpu à le faire? Bien sûr, est la charge suivante un lot, ce pré-traitement par lots et après tirage sur les résultats du journal sur le gpu, post-traitement, résumé d'écriture même enregistrer des modèles, cette série de dépenses doivent compter sur cpu complète. Nous regardons souvent le code lit comme suit:

        create_graph()
create_model_saver()
create_summary_writer()
create_session()
do_init()
for i in range(num_train_steps):
    load_batch(...)                # cpu
    preprocess(...)                # cpu
    feed_dict = {...}              # cpu
    fetch_list = [...]             # cpu
    buf = session.run(fetch_list, feed_dict)    # gpu
    postprocess(buf)               # cpu
    print(...)                     # cpu
    if i % x == 0:
        summary_writer.write(...)  # cpu
    if i % xx == 0:
        model_saver.save(...)      # cpu
      

Regardez, en particulier prétraiter (...) la tâche est lourde, il est facile de provoquer le code dans le cpu a également été exécuté pendant un certain temps, l'utilisation de gpu ira naturellement et le changement cyclique elle.

Est-il possible de réduire le temps cpu, améliorer le temps de gpu?

Une très auto (stupide) puis (stupide) idée est de former tous les codes de réécriture pas utiliser api tf mille millions, et même la couche la plus externe qui for i in range(num_train_steps)peut effectivement être utilisé tf.while_loop réécrire. Ah, le soir vraiment petit donc j'ai essayé, puis trouvé

 

v2-bde01235526089755e5a6895b1db83ec_b.jpg

TF api Ce meow spécial est ce fantôme! python numpy avec une variété de fonctions intégrées et incompatible avec le comportement du même nom, mais ce que l'enfer! FML api moins cet argument comment puis-je faire? une ligne de code en python pour être en mesure d'obtenir les choses pourquoi j'ai écrit quelques lignes? ?

 

v2-b347580774f2421578d25b1429cacbd4_b.jpg

Donc, en plus de la programmation fonctionnelle Daniel, petite soirée fortement recommandé de ne pas répéter les mêmes erreurs! Surtout ceux d'entre nous rencontre cri de compilation, après avoir vu 90 Lisp fée crash!

Donc aucun moyen de décrire toute la boucle de train dans le calcul de la carte?

Ne pas avoir peur Ne pas avoir peur, de bonnes nouvelles était en fait paquet tensorflow a particulièrement bien (et plus) avec (fosse) API à la boucle de train entier supérieur peut être facilement encapsulées dans le calcul de la figure, pour atteindre super haute utilisation et GPU efficacité de la formation!

estimateur

Pourquoi ne l'ignorez pas appelé estimateur, juste besoin de savoir que nous voulons juste faire de la base a donné un bon paquet sur la ligne. Le libellé de cette classique se déplacer un peu plus

        1. create_model()
2. create_model_saver()
3. create_summary_writer()
4. create_session()
5. do_init()
6. for i in range(num_train_steps):
7.      load_batch(...)                # cpu
8.      preprocess(...)                # cpu
9.      feed_dict = {...}              # cpu
10.     fetch_list = [...]             # cpu
11.     buf = session.run(fetch_list, feed_dict)    # gpu
12.     postprocess(buf)               # cpu
13.     print(...)                     # cpu
14.     if i % x == 0:
15.         summary_writer.write(...)  # cpu
16.     if i % xx == 0:
17.         model_saver.save(...)      # cpu
      

1-5 sont estimateur en ligne emballé Eh bien, vous venez de mettre dans la configuration de l'estimateur peut être des amis ~ RunConfig

7-9 ligne paquet aussi bien, il vous suffit de charger le code et l'ensemble de données associées en fonction de prétraitement de ~ Superposer input_fn estimator.train

Ligne 10 encapsule aussi bien, il vous suffit de chercher la perte, estimateur train_op jeté EstimatorSpec de ~

Ligne 11 encapsule aussi bien, il vous suffit de décrire le calcul modèle de fonction estimateur surimposé de la figure model_fn ~

12-13 lignes ne vous inquiétez pas au sujet des détails, et la perte global_step automatiquement, et le reste - et LoggingTensorHook tf.Print jeté

14-17 écrivez-vous pas une ligne, l'auto-complétion

╮ (╯ ▽ ╰) ╭

Après repas un toss, nous avons constaté qu'il améliore considérablement l'utilisation des GPU - presque égale à 80%, voire 90%. Il n'y a donc pas de place pour la presse, il?

En fait, quand une analyse minutieuse constatera que bien que la plupart du code écrit dans l'estimateur pour le calcul de l' Ituri, mais il est encore chargé et pré-traitement des données du cpu où série conduite Ouais, mais il y a un tel lot de 128 échantillons , alors le estimaor interne exécuter chaque étape dans le temps ou à attendre les 128 échantillons en série de tâche traitée. Ce dernier est évidemment le goulot d' étranglement , il! Il n'y a aucun moyen de l' éliminer? · Bien sûr, cela est

tf.data

API de jeu de données TF peut dire des gens aiment à la haine, et il ne semble fournir un chemin pour l'ensemble du tableau de précalculée sont déplacés le traitement parallèle, mais! Si vous API vraiment entièrement tensorflow à faire un prétraitement complexe, va vraiment rendre les gens fous QAQ donc ici avant avec tf.data, petite soirée fortement recommandé que la première série de données dans une pré-transformation regard traité, y compris faire mot, ne couper, et ainsi faire word2id, mais le rembourrage et input_mask peut rester dans le TF qui ne , après tout, seulement besoin d' une ligne.

Qu'après cela est pré - traitement fini, le stockage de données comment cela serait plus pratique et lecture ultérieure accord avec elle? De loin la façon la plus recommandée est d'utiliser tf.recordspour le stockage, le disque, la mémoire, IO et l' efficacité du stockage sera plus rapide par rapport aux méthodes traditionnelles, x et y ne se séparent pas. Bien sûr, cela n'est pas directement inconvénient regard ouvert sur l'ensemble de données ╮ (¯ ▽ ¯ « ») ╭ Après tout, l'ensemble de données a été transformé en un fichier binaire.

Mais ne veux vraiment pas tf.record paresseux, alors petite soirée est fortement recommandé que x et y stockés séparément , et essayer de faire les tf.data finition nécessaire au- dessus des données de pré-lecture, quand pour éviter difficile à utiliser API chaîne et la pression d'exploitation sous - jacent pour réduire la formation de cpu et de la mémoire.

tf.data il y a un gros avantage que nous pouvons soutenir d'une manière très naturelle pour lire des données en continu , ces données ne se produiront pas face à de grands ensembles de données après les graphiques de charge de découverte occupés embarras de ╮ ( ¯ ▽ ¯ "") ╭

Comme si parler depuis si longtemps, ne dit pas comment ou tf.data accélérer QAQ, entrent en la matière.

Pensez Kazakhstan, tf.data inutile, nous écrivons le code fait heurtons est comme ceci:

 

v2-1cc7ed94295fe3bb8ef66fb01a95233d_b.jpg

Ceci est aussi le début de l'article petit soir pour expliquer pourquoi les raisons importantes ne peuvent pas monter et changer régulièrement l'utilisation de gpu. Donc, nous ne pouvons pas éliminer au ralenti, comme celui-ci se préparer le processus de parallèle et le former?

 

v2-989015918c2fa02d6d8e244fa81c6bf6_b.jpg

Bien sûr, vous pouvez! à savoir

prefetch

Il peut être compris à partir des moyens de prélecture prélecture l'étape suivante pour charger le lot. Utilisez tf.data qui est appelé prélecture api magique peut facilement compléter, c'est là l'argument buffer_size api est de parler est à combien d'extraction supplémentaires, tels que buffer_size = 1, alors nous devons précharger un lot, puis tous les modèles préparer un lot après des temps d'achèvement, puis il préparera automatiquement un lot de plus, donc la prochaine étape de train vient directement de la mémoire peut être retirée dans cette pré-préparer un bon ami de lot. (Pour plus de détails, voir plus loin)

Attendez, le dessin des mots de fantaisie, il y a du bois, il a constaté que si un lot préparer très court temps si en effet les deux mondes, mais si vous avez pris assez long, surtout une fois prélecture plusieurs lots, puis, préparer une fois avec plus de quand un train d'un pas, le rendement de chaque étape dans le train sera limitée à l'efficacité préparer. Si cette question est agrandie comme indiqué sur la figure.

 

v2-807c180534fa39d9b4d8eccfc0aff9ab_b.jpg

Regardez, préparer trop longtemps lors de son utilisation entraînera le train de terminer un ralenti gpu étape pour (bien que, en fait, l'étape suivante dans le lot et peut déjà préparer)

Nous ne pouvons pas garantir la scène est moins que le train lorsque la phase de préparation à l'utilisation de celui-ci?

cartographie parallèle

Une idée très simple est bien sûr de faire des amis - si la taille du lot de traitement parallèle échantillon est de 128, la taille prélecture = 1, puis préparer un lot à série pré - traitement d'exécution 128 * 2 = 256 fois, mais si nous ouvrons quatre fils à terme, il est rapide coup d' œil beaucoup plus attrayant. Heureusement, nous ne devons pas faire exploser vos propres mains multithreading, tf.data.Dataset il y a une carte de paramètres (pré-traitement) en fonction num_parallel_calls, peut être affecté à ce paramètre en parallèle l' analyse syntaxique. Comme le montre,

 

v2-2c2df2a40a1a57081d84314e1acc41f1_b.jpg

Donc, tant que buffer_size et cartographier la prélecture de num_parrellel_calls obtenir approprié train, essentiellement ininterrompue peut atteindre, ce qui est l' utilisation presque 100% du GPU!

Eh bien, je pensais à comprendre le code est facile à comprendre. Non utilisé tf.record, découle directement de la procédure lorsque les données texte brut typiques prétraité ensembles de données de charge

        def build_input(..):
    x = tf.data.XXDataset(..)
    x = x.map(..., num_parallel_calls=N)        # parellel

    y = tf.data.XXDataset(..)
    y = y.map(..., num_parallel_calls=N)

    dataset = tf.data.Dataset.zip((x, y))
    dataset = dataset.repeat(num_epochs)    
    if is_train:
        dataset = dataset.shuffle(..)
    dataset = dataset.batch(batch_size)
    dataset = dataset.prefetch(buffer_size=1)   # prefetch
    iterator = dataset.make_xx_iterator()
    return iterator.get_next()
      

Bien sûr, si l'utilisation d' tf.recordaprès, respectivement, ne lisent pas les données d'un fichier à la fois les amis de x et y, intéressés par les chaussures pour enfants peut devoir aller découvrir.

prestations supplémentaires

Bien sûr, juste la migration de code traditionnel tf.data estimateur +, il pourrait ne pas adapter, la chose la plus importante en mode débogage, comme session.run directe (debug_tensor), alors comment ne pas comme avant?

En général tenseur d'impression nous, il y a deux cas, on est la nécessité d'imprimer une ou plusieurs fois pour localiser le problème lors du calcul de la mauvaise carte, on est comme global_step, perte, etc. besoin vérification périodique. Dans les deux cas, avant la session.run habitude quand vous voulez imprimer le tenseur exécuter aussi, et maintenant ces deux cas peuvent être distingués traiter ce.

Pour la première, petite soirée se sentent le plus efficace ou branché directement tf.Print (..), facile à utiliser, la capacité de débogage est très puissant dans le calcul de l' Ituri! Si vous avez besoin d'imprimer à l' étape mondiale, plus un tf.cond pour l' obtenir. Pour la deuxième après, en fait, pas globale, puis estimateur par défaut et la perte seront imprimées, si d' autres nécessitent tenseur impression périodique, puis utilisez tf.train.LoggingTensorHook-emballé puis jeté dans l'habitude de fait estimator.train en elle ~ se sentent encore très pratique m (_ _ ) m

Enfin, le monde ne veut pas graphiques gratuits

Publié 33 articles originaux · louanges gagnées 0 · Vues 3284

Je suppose que tu aimes

Origine blog.csdn.net/xixiaoyaoww/article/details/104553499
conseillé
Classement