我知道我可以测量对sess.run()
的调用的执行时间,但是是否可以获得更精细的粒度并测量单个操作的执行时间?
答案 0 :(得分:97)
我已经使用Timeline
object来获取图表中每个节点的执行时间:
sess.run()
,但也指定了可选参数options
和run_metadata
Timeline
数据run_metadata.step_stats
对象
这是一个测量矩阵乘法性能的示例程序:
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)
然后,您可以打开Google Chrome浏览器,转到页面chrome://tracing
并加载timeline.json
文件。
你应该看到类似的东西:
答案 1 :(得分:21)
在公开发布中还没有办法做到这一点。我们知道这是一个重要的功能,我们正在努力。
答案 2 :(得分:18)
由于在搜索“Tensorflow Profiling”时这是高位,请注意当前(2017年末,TensorFlow 1.4)获取时间轴的方式是使用ProfilerHook。这适用于tf.Estimator中的MonitoredSessions,其中tf.RunOptions不可用。
estimator = tf.estimator.Estimator(model_fn=...)
hook = tf.train.ProfilerHook(save_steps=10, output_dir='.')
estimator.train(input_fn=..., steps=..., hooks=[hook])
答案 3 :(得分:12)
您可以使用runtime statistics提取此信息。您将需要执行以下操作(请查看上述链接中的完整示例):
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)
比打印它更好,你可以在tensorboard中看到它:
此外,单击节点将显示确切的总内存, 计算时间和张量输出大小。
答案 4 :(得分:10)
为了更新这个答案,我们确实有一些CPU分析功能,专注于推理。如果您查看https://github.com/tensorflow/tensorflow/tree/master/tensorflow/tools/benchmark,您会看到一个程序,您可以在模型上运行以获得每个操作时间。
答案 5 :(得分:2)
对于 Olivier Moindrot 的答案下的 fat-lobyte 的评论,如果你想收集所有会话的时间表,你可以改变“{{1} }“to”open('timeline.json', 'w')
“。
答案 6 :(得分:2)
从Tensorflow 1.8开始,使用tf.profile.Profiler
here就是一个很好的例子。
答案 7 :(得分:0)
最近由Uber发布的SBNet自定义操作库(http://www.github.com/uber/sbnet)具有基于cuda事件的计时器的实现,可以按以下方式使用:
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
请注意,子图的任何部分都可以是异步的,您应该非常小心地指定timer ops的所有输入和输出依赖项。否则,计时器可能会无序地插入到图形中,您可能会得到错误的时间。我找到了时间轴和time.time()时间非常有限的实用程序,用于分析Tensorflow图。另请注意,cuda_timer API将在默认流上同步,这是当前设计的,因为TF使用多个流。
话虽如此,我个人建议切换到PyTorch :)开发迭代更快,代码运行速度更快,一切都不那么痛苦。
从tf.Session(可能是巨大的)减去开销的另一种有点hacky和神秘的方法是将图形复制N次并将其运行为变量N,求解未知固定开销的方程式。即你在session.run()周围测量N1 = 10和N2 = 20,你知道你的时间是t,开销是x。像
这样的东西N1*x+t = t1
N2*x+t = t2
解决x和t问题。缺点是这可能需要大量内存并且不一定准确:)同时确保您的输入完全不同/随机/独立否则TF将折叠整个子图并且不运行N次...享受TensorFlow的乐趣: )
答案 8 :(得分:0)
2.0兼容答案:您可以在 __init__(text)
中使用Profiling
。
该代码为:
Keras Callback
有关如何进行性能分析的更多详细信息,请参阅此Tensorboard Link。