第一次 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() 的执行与后来的运行截然不同。为啥?的主要内容,如果未能解决你的问题,请参考以下文章

Session.run() & Tensor.eval()

CS 20_Overview of Tensorflow

用 tf.data API 替换 tf.placeholder 和 feed_dict

如何使用 TFRecord 数据集使 TensorFlow + Keras 快速运行?

jquery点击按钮或链接,第一次与第二次执行不同的事件

是否建议在 Oracle 中循环执行查询与一次性执行查询以获得显着的性能提升?