web-dev-qa-db-fra.com

Puis-je mesurer le temps d'exécution d'opérations individuelles avec TensorFlow?

Je sais que je peux mesurer le temps d'exécution d'un appel à sess.run(), mais est-il possible d'obtenir une granularité plus fine et de mesurer le temps d'exécution d'opérations individuelles?

60
user3559888

Il n'y a pas encore de moyen de le faire dans la version publique. Nous sommes conscients que c'est une fonctionnalité importante et nous y travaillons.

21
Ian Goodfellow

J'ai utilisé l'objet Timeline pour obtenir le temps d'exécution pour chaque nœud du graphique:

  • vous utilisez un sess.run() classique mais spécifiez également les arguments optionnels options et run_metadata
  • vous créez ensuite un objet Timeline avec les données run_metadata.step_stats

Voici un exemple de programme mesurant les performances d'une multiplication matricielle:

import tensorflow as tf
from tensorflow.python.client import timeline

x = tf.random_normal([1000, 1000])
y = tf.random_normal([1000, 1000])
res = tf.matmul(x, y)

# Run the graph with full trace option
with tf.Session() as sess:
    run_options = tf.RunOptions(trace_level=tf.RunOptions.FULL_TRACE)
    run_metadata = tf.RunMetadata()
    sess.run(res, options=run_options, run_metadata=run_metadata)

    # Create the Timeline object, and write it to a json
    tl = timeline.Timeline(run_metadata.step_stats)
    ctf = tl.generate_chrome_trace_format()
    with open('timeline.json', 'w') as f:
        f.write(ctf)

Vous pouvez ensuite ouvrir Google Chrome, aller à la page chrome://tracing et charger le fichier timeline.json . Vous devriez voir quelque chose comme:

 timeline

91
Olivier Moindrot

Etant donné que ceci est élevé lors de la recherche de "Tensorflow Profiling" sur Google, notez que la méthode actuelle (fin 2017, TensorFlow 1.4) pour obtenir la timeline utilise un ProfilerHook . Cela fonctionne avec les sessions surveillées dans tf.Estimator où les options tf.RunOptions ne sont pas disponibles.

estimator = tf.estimator.Estimator(model_fn=...)
hook = tf.train.ProfilerHook(save_steps=10, output_dir='.')
estimator.train(input_fn=..., steps=..., hooks=[hook])
14
Urs

Vous pouvez extraire ces informations à l’aide de statistiques d’exécution . Vous devrez faire quelque chose comme ceci (voir l'exemple complet dans le lien mentionné ci-dessus):

run_options = tf.RunOptions(trace_level=tf.RunOptions.FULL_TRACE)
run_metadata = tf.RunMetadata()
sess.run(<values_you_want_to_execute>, options=run_options, run_metadata=run_metadata)
your_writer.add_run_metadata(run_metadata, 'step%d' % i)

Mieux que de simplement l’imprimer, vous pouvez le voir sur le tensorboard:

De plus, cliquer sur un nœud affichera la mémoire totale exacte, temps de calcul et tailles de sortie du tenseur.

 [Example from link

11
Salvador Dali

Pour mettre à jour cette réponse, nous disposons de certaines fonctionnalités pour le profilage de la CPU, axées sur l'inférence. Si vous regardez https://github.com/tensorflow/tensorflow/tree/master/tensorflow/tools/benchmark , vous verrez un programme que vous pouvez exécuter sur un modèle pour obtenir des minutages par opération.

10
Pete Warden

Pour les commentaires de fat-lobyte under Olivier Moindrot , vous pouvez remplacer "open('timeline.json', 'w')" par "open('timeline.json', 'a')" si vous souhaitez rassembler la chronologie de toutes les sessions. 

2
Cheney

Depuis Tensorflow 1.8, il existe un très bon exemple d'utilisation du tf.profile.Profilerici .

2
nitred

Pour profiler automatiquement les sessions TensorFlow, vous pouvez utiliser le profileur StackImpact . Pas besoin d'instrumenter des sessions ou d'ajouter des options. Il vous suffit d’initialiser le profileur:

import stackimpact

agent = stackimpact.start(
    agent_key = 'agent key here',
    app_name = 'MyApp')

Les profils de temps d'exécution et de mémoire seront disponibles dans le tableau de bord.

Informations détaillées dans cet article: Profilage TensorFlow dans les environnements de développement et de production .

Disclaimer: Je travaille pour StackImpact.

0
logix

La bibliothèque d'opérations personnalisées Uber SBNet ( http://www.github.com/uber/sbnet récemment publiée) comporte une implémentation de timers basés sur des événements cuda, qui peuvent être utilisés de la manière suivante:

with tf.control_dependencies([input1, input2]):
    dt0 = sbnet_module.cuda_timer_start()
with tf.control_dependencies([dt0]):
    input1 = tf.identity(input1)
    input2 = tf.identity(input2)

### portion of subgraph to time goes in here

with tf.control_dependencies([result1, result2, dt0]):
    cuda_time = sbnet_module.cuda_timer_end(dt0)
with tf.control_dependencies([cuda_time]):
    result1 = tf.identity(result1)
    result2 = tf.identity(result2)

py_result1, py_result2, dt = session.run([result1, result2, cuda_time])
print "Milliseconds elapsed=", dt

Notez que n'importe quelle partie du sous-graphe peut être asynchrone. Vous devez donc faire très attention en spécifiant toutes les dépendances d'entrée et de sortie pour les opérations du minuteur. Sinon, le chronomètre pourrait être inséré dans le graphique dans le désordre et vous pourriez obtenir un temps erroné. J'ai trouvé les deux timeline et time.time () d'un utilitaire très limité pour le profilage de graphiques Tensorflow. Notez également que les API cuda_timer se synchroniseront sur le flux par défaut, qui est actuellement voulu par conception, car TF utilise plusieurs flux.

Cela dit, je recommande personnellement de passer à PyTorch :) L’itération de développement est plus rapide, le code est plus rapide et tout est beaucoup moins pénible.

Une autre approche quelque peu hacky et obscure pour soustraire le temps système de tf.Session (qui peut être énorme) consiste à reproduire le graphique N fois et à l’exécuter pour une variable N, en résolvant une équation de temps système fixe inconnu. C'est à dire. vous mesureriez environ session.run () avec N1 = 10 et N2 = 20 et vous savez que votre temps est t et que le temps système est x. Donc quelque chose comme

N1*x+t = t1
N2*x+t = t2

Résoudre pour x et t. L'inconvénient est que cela peut nécessiter beaucoup de mémoire et n'est pas nécessairement précis :) Assurez-vous également que vos entrées sont complètement différentes/aléatoires/indépendantes, sinon TF pliera l'intégralité du sous-graphique et ne l'exécutera pas N fois ... Amusez-vous avec TensorFlow: )

0
Andrei Pokrovsky