第一次 tf.session.run() 的执行与后来的运行截然不同。为啥?
Posted
技术标签:
【中文标题】第一次 tf.session.run() 的执行与后来的运行截然不同。为啥?【英文标题】:First tf.session.run() performs dramatically different from later runs. Why?第一次 tf.session.run() 的执行与后来的运行截然不同。为什么? 【发布时间】:2017-12-17 05:23:22 【问题描述】:这里有一个例子来说明我的意思: 第一个 session.run():First run of a TensorFlow session
稍后 session.run():Later runs of a TensorFlow session
我知道 TensorFlow 在这里进行了一些初始化,但我想知道它在源代码中的哪个位置。 这发生在 CPU 和 GPU 上,但在 GPU 上效果更明显.例如,在显式 Conv2D 操作的情况下,第一次运行在 GPU 流中具有大量的 Conv2D 操作。事实上,如果我改变 Conv2D 的输入大小,它可以从几十到几百个流 Conv2D 操作。然而,在以后的运行中,GPU 流中始终只有五个 Conv2D 操作(无论输入大小如何)。在 CPU 上运行时,我们在第一次运行时保留了与以后运行相同的操作列表,但我们确实看到了相同的时间差异。
TensorFlow 源代码的哪一部分是造成这种行为的原因? GPU 操作在哪里“拆分”?
感谢您的帮助!
【问题讨论】:
【参考方案1】:tf.nn.conv_2d()
操作在第一次 tf.Session.run()
调用上运行需要更长的时间,因为默认情况下,TensorFlow 使用 cuDNN 的自动调整工具来选择如何尽可能快地运行后续卷积。你可以看到自动调谐调用here。
您可以使用undocumented environment variable 来禁用自动调谐。在启动运行 TensorFlow 的进程(例如 python
解释器)时设置 TF_CUDNN_USE_AUTOTUNE=0
以禁用它。
【讨论】:
谢谢,这很有帮助!由此,我假设在 GPU 上运行时将常规操作拆分为多个流操作的所有情况都是由于 cuDNN 和/或 cuBLAS 造成的? 我不是 100% 确定,但我认为在某些情况下,Eigen 实现的内核会生成多个流操作(例如多个小型 memcpy 操作)。然而,大多数性能关键内核使用 cuDNN/cuBLAS。以上是关于第一次 tf.session.run() 的执行与后来的运行截然不同。为啥?的主要内容,如果未能解决你的问题,请参考以下文章
用 tf.data API 替换 tf.placeholder 和 feed_dict