Recherche…


Utilisez Graph.finalize () pour intercepter les nœuds ajoutés au graphique

Le mode d'utilisation de TensorFlow le plus courant consiste à créer d' abord un graphe de flux de données des opérateurs TensorFlow (comme tf.constant() et tf.matmul() , puis à exécuter des étapes en appelant la méthode tf.Session.run() dans une boucle (par exemple, un boucle de formation).

Une source courante de fuites de mémoire est celle où la boucle de formation contient des appels qui ajoutent des nœuds au graphe et qui s'exécutent à chaque itération, ce qui entraîne une croissance du graphe. Celles-ci peuvent être évidentes (par exemple, un appel à un opérateur TensorFlow comme tf.square() ), implicite (par exemple un appel à une fonction de bibliothèque TensorFlow qui crée des opérateurs comme tf.train.Saver() ) ou subtile (par exemple un appel à un opérateur surchargé sur un tf.Tensor et un tableau NumPy, qui appelle implicitement tf.convert_to_tensor() et ajoute un nouveau tf.constant() au graphique).

La méthode tf.Graph.finalize() peut aider à détecter les fuites comme ceci: elle marque un graphe en lecture seule et déclenche une exception si quelque chose est ajouté au graphe. Par exemple:

loss = ...
train_op = tf.train.GradientDescentOptimizer(0.01).minimize(loss)
init = tf.initialize_all_variables()

with tf.Session() as sess:
    sess.run(init)
    sess.graph.finalize()  # Graph is read-only after this statement.

    for _ in range(1000000):
        sess.run(train_op)
        loss_sq = tf.square(loss)  # Exception will be thrown here.
        sess.run(loss_sq)

Dans ce cas, l'opérateur surchargé * tente d'ajouter de nouveaux noeuds au graphique:

loss = ...
# ...
with tf.Session() as sess:
    # ...
    sess.graph.finalize()  # Graph is read-only after this statement.
    # ...
    dbl_loss = loss * 2.0  # Exception will be thrown here.

Utilisez l'allocateur tcmalloc

Pour améliorer les performances d'allocation de mémoire, de nombreux utilisateurs de TensorFlow utilisent souvent tcmalloc au lieu de l'implémentation malloc() par défaut, car tcmalloc souffre moins de la fragmentation lors de l'allocation et de la désallocation d'objets volumineux (nombreux tenseurs). Certains programmes TensorFlow nécessitant beaucoup de mémoire ont été connus pour faire fuir l' espace d'adressage du tas (tout en libérant tous les objets individuels qu'ils utilisent) avec la valeur par défaut malloc() , mais ils se sont bien tcmalloc après le passage à tcmalloc . De plus, tcmalloc inclut un profileur de tas , qui permet de tcmalloc les fuites restantes.

L'installation de tcmalloc dépendra de votre système d'exploitation, mais les éléments suivants fonctionnent sur Ubuntu 14.04 (trusty) (où script.py est le nom de votre programme TensorFlow Python):

$ sudo apt-get install google-perftools4
$ LD_PRELOAD=/usr/lib/libtcmalloc.so.4 python script.py ...

Comme indiqué ci-dessus, le simple fait de passer à tcmalloc peut résoudre de nombreuses fuites apparentes. Toutefois, si l'utilisation de la mémoire continue de croître, vous pouvez utiliser le profileur de tas comme suit:

$ LD_PRELOAD=/usr/lib/libtcmalloc.so.4 HEAPPROFILE=/tmp/profile python script.py ...

Après avoir exécuté la commande ci-dessus, le programme écrit régulièrement des profils sur le système de fichiers. La séquence de profils sera nommée:

  • /tmp/profile.0000.heap
  • /tmp/profile.0001.heap
  • /tmp/profile.0002.heap
  • ...

Vous pouvez lire les profils à l'aide de l'outil google-pprof , qui (par exemple, sur Ubuntu 14.04) peut être installé dans le cadre du package google-perftools . Par exemple, pour regarder le troisième instantané collecté ci-dessus:

$ google-pprof --gv `which python` /tmp/profile.0002.heap

En exécutant la commande ci-dessus, une fenêtre GraphViz apparaîtra, affichant les informations du profil sous la forme d'un graphique dirigé.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow