Tensorflow - 推理时间评估

Pel*_*ups 3 evaluation inference tensorflow

我正在使用 Tensorflow 评估不同的图像分类模型,特别是使用不同设备的推理时间。我想知道是否必须使用预训练模型。我使用一个脚本生成 1000 个随机输入图像,将它们一一输入到网络,并计算平均推理时间。

谢谢 !

Pat*_*wie 5

让我首先发出警告:

大多数人以错误的方式完成了神经网络的正确基准测试。对于 GPU,有磁盘 I/O、内存带宽、PCI 带宽、GPU 速度本身。然后还有像feed_dict在 TensorFlow 中使用这样的实现错误。对于这些模型的有效训练也是如此。

让我们从一个简单的例子开始,考虑 GPU

import tensorflow as tf
import numpy as np

data = np.arange(9 * 1).reshape(1, 9).astype(np.float32)
data = tf.constant(data, name='data')

activation = tf.layers.dense(data, 10, name='fc')

with tf.Session(config=tf.ConfigProto(log_device_placement=True)) as sess:
    sess.run(tf.global_variables_initializer())
    print sess.run(activation)
Run Code Online (Sandbox Code Playgroud)

它所做的只是创建一个常量张量并应用一个全连接层。所有的操作都放在GPU上:

fc/bias: (VariableV2): /job:localhost/replica:0/task:0/device:GPU:0
2018-01-25 09:55:01.587959: I tensorflow/core/common_runtime/placer.cc:874] fc/bias: (VariableV2)/job:localhost/replica:0/task:0/device:GPU:0
fc/bias/read: (Identity): /job:localhost/replica:0/task:0/device:GPU:0
2018-01-25 09:55:01.587970: I tensorflow/core/common_runtime/placer.cc:874] fc/bias/read: (Identity)/job:localhost/replica:0/task:0/device:GPU:0
fc/bias/Assign: (Assign): /job:localhost/replica:0/task:0/device:GPU:0
2018-01-25 09:55:01.587979: I tensorflow/core/common_runtime/placer.cc:874] fc/bias/Assign: (Assign)/job:localhost/replica:0/task:0/device:GPU:0
fc/kernel: (VariableV2): /job:localhost/replica:0/task:0/device:GPU:0
2018-01-25 09:55:01.587988: I tensorflow/core/common_runtime/placer.cc:874] fc/kernel: (VariableV2)/job:localhost/replica:0/task:0/device:GPU:0
fc/kernel/read: (Identity): /job:localhost/replica:0/task:0/device:GPU:0
...
Run Code Online (Sandbox Code Playgroud)

看起来不错,对吧?对该图进行基准测试可以粗略估计 TensorFlow 图的执行速度。只需替换tf.layers.dense为您的网络即可。如果您接受使用 pythons 包的开销time,那么您就完成了。

但不幸的是,这并不是故事的全部。将结果从访问设备内存(GPU)的张量运算复制回'fc/BiasAdd:0'并复制到主机内存(CPU、RAM)。因此,在某些时候 PCI 带宽会受到限制。某个地方也有一个 python 解释器,占用 CPU 周期。

此外,操作被放置在 GPU 上,而不是值本身。不确定您使用的是哪个 TF 版本。但即使tf.const是旧版本,也不能保证将其放置在 GPU 上。我只是在编写自己的操作时才注意到这一点。顺便说一句:请参阅我关于 TF 如何决定在哪里进行操作的其他答案。

现在,最困难的部分是:这取决于你的图表。坐在tf.cond/tf.where某个地方会让事情更难进行基准测试。现在,您需要经历在有效训练深度网络时需要解决的所有这些困难。这意味着,一个简单的 const 无法解决所有情况。

解决方案首先通过运行将一些值直接放入/暂存到 GPU 内存中

stager = data_flow_ops.StagingArea([tf.float32])
enqeue_op = stager.put([dummy])
dequeue_op = tf.reduce_sum(stager.get())

for i in range(1000):
    sess.run(enqeue_op)
Run Code Online (Sandbox Code Playgroud)

预先。但同样,TF 资源管理器正在决定将值放在哪里(并且不能保证值的排序或删除/保留)。

总而言之:基准测试是一项非常复杂的任务,因为基准测试 CUDA 代码很复杂。现在,您有了 CUDA 和 Python 部分。这是一项高度主观的任务,具体取决于您对哪些部分感兴趣(只是图形,包括磁盘 I/O,...)

tf.const我通常使用示例中的输入运行图表,并使用分析器查看图表中发生的情况。

有关如何提高运行时性能的一些一般想法,您可能需要阅读 Tensorflow性能指南