Posso misurare il tempo di esecuzione delle singole operazioni con TensorFlow?

So che posso misurare il tempo di esecuzione di una chiamata a sess.run() , ma è ansible ottenere una granularità più fine e misurare il tempo di esecuzione delle singole operazioni?

Non c’è ancora un modo per farlo nella versione pubblica. Siamo consapevoli che è una caratteristica importante e ci stiamo lavorando.

Ho usato l’ object Timeline per ottenere il tempo di esecuzione per ciascun nodo nel grafico:

  • si utilizza un classico sess.run() ma si specificano anche le options opzionali degli argomenti e run_metadata
  • quindi si crea un object Timeline con i dati run_metadata.step_stats

Ecco un programma di esempio che misura le prestazioni di una moltiplicazione di matrici:

 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) 

Puoi quindi aprire Google Chrome, andare alla pagina chrome://tracing e caricare il file timeline.json . Dovresti vedere qualcosa come:

sequenza temporale

È ansible estrarre queste informazioni utilizzando le statistiche di runtime . Dovrai fare qualcosa di simile (controlla l’esempio completo nel link sopra indicato):

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

Meglio della semplice stampa puoi vederlo in tensore:

Inoltre, facendo clic su un nodo verrà visualizzata la memoria totale esatta, il tempo di calcolo e le dimensioni di uscita del tensore.

[Esempio dal link

Per aggiornare questa risposta, abbiamo alcune funzionalità per il profilo della CPU, focalizzato sull’inferenza. Se si guarda https://github.com/tensorflow/tensorflow/tree/master/tensorflow/tools/benchmark , verrà visualizzato un programma che è ansible eseguire su un modello per ottenere gli intervalli per utente.

Poiché questo è alto quando si cerca su google “Profilo di Tensorflow”, si noti che il modo corrente (verso la fine del 2017, TensorFlow 1.4) per ottenere la linea temporale è l’utilizzo di ProfilerHook . Funziona con MonitoredSession in tf.Estimator dove tf.RunOptions non è disponibile.

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

Per i commenti di fat-lobyte sotto la risposta di Olivier Moindrot , se si desidera raccogliere la cronologia su tutte le sessioni, è ansible modificare ” open('timeline.json', 'w') ” a ” open('timeline.json', 'a') “.

A partire da Tensorflow 1.8, c’è un ottimo esempio per l’utilizzo di tf.profile.Profiler qui .

Per definire automaticamente le sessioni TensorFlow, è ansible utilizzare il profiler StackImpact . Non è necessario eseguire sessioni strumentali o aggiungere opzioni. Hai solo bisogno di inizializzare il profiler:

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

Sia il tempo di esecuzione che i profili di memoria saranno disponibili in Dashboard.

Informazioni dettagliate in questo articolo: Profilo TensorFlow negli ambienti di sviluppo e produzione .

Disclaimer: lavoro per StackImpact.

Recentemente rilasciato dalla libreria op personalizzata di Uber SBNet ( http://www.github.com/uber/sbnet ) ha un’implementazione di timer basati su eventi cuda, che possono essere utilizzati nel modo seguente:

 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 

Nota che qualsiasi porzione di sottografo può essere asincrona dovresti stare molto attento a specificare tutte le dipendenze di input e output per le operazioni di timer. In caso contrario, il timer potrebbe essere inserito nel grafico fuori servizio e si può ottenere un tempo errato. Ho trovato sia la timeline che il time.time () timing di un’utilità molto limitata per la profilazione di grafici Tensorflow. Si noti inoltre che le API di cuda_timer si sincronizzeranno sul stream predefinito, che è attualmente in progettazione poiché TF utilizza più flussi.

Detto questo, personalmente raccomando di passare a PyTorch 🙂 L’iter di sviluppo è più veloce, il codice scorre più veloce e tutto è molto meno doloroso.

Un altro approccio un po ‘hacky e arcano per sottrarre l’overhead da tf.Session (che può essere enorme) è replicare il grafico N volte ed eseguirlo per una variabile N, risolvendo un’equazione di overhead fisso sconosciuto. Ad esempio, misureresti session.run () con N1 = 10 e N2 = 20 e saprai che il tuo tempo è t e il sovraccarico è x. Quindi qualcosa di simile

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

Risolvi per xe t. Il rovescio della medaglia è che potrebbe richiedere molta memoria e non è necessariamente accurato 🙂 Assicurati inoltre che i tuoi input siano completamente diversi / casuali / indipendenti altrimenti TF ripiegherà l’intero sottografo e non lo eseguirà N volte … Divertiti con TensorFlow: )