【问题标题】:Tensorflow - Inference time evaluationTensorflow - 推理时间评估
【发布时间】:2018-01-25 08:08:37
【问题描述】:

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

谢谢!

【问题讨论】:

    标签: tensorflow evaluation inference


    【解决方案1】:

    让我从一个警告开始:

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

    让我们从一个考虑 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)
    

    它所做的只是创建一个 const 张量并应用一个全连接层。 所有操作都放在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
    ...
    

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

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

    此外,操作放置在 GPU 上,而不需要 本身。不确定,您使用的是哪个 TF 版本。但即使是tf.const 也不能保证在旧版本中放置在 GPU 上。我只有在编写自己的 Ops 时才注意到这一点。顺便说一句:在how TF decides where to place operations 上查看我的其他答案。

    现在,最难的部分是:这取决于您的图表。将tf.cond/tf.where 放在某个地方会使事情更难进行基准测试。现在,您需要经历在有效训练深度网络时需要解决的所有这些难题。意思是,一个简单的 const 不能解决所有情况。

    解决方案首先通过运行将/staging一些值直接放入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)
    

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

    总结一下:基准测试是一项非常复杂的任务,因为基准测试 CUDA 代码很复杂。现在,你有了 CUDA 和另外的 python 部分。 这是一项非常主观的任务,取决于您对哪些部分感兴趣(只是图表,包括磁盘 i/o,...)

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

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

    【讨论】:

    • 感谢您提供如此详细的回答!
    • 很好的答案!快速提问。在tensorflow 上进行推理的最佳实践是什么? [我在 tensorflow 文档中读到 feed_dict 很慢,应该只用于开发建议。我正在寻找一种进行快速推理的方法(可以排队 - 虽然 tensorflow 说使用 tf.data 但它似乎只对训练有用?)]
    【解决方案2】:

    所以,澄清一下,您只对每个推理步骤的运行时间感兴趣,而不对准确性或任何与 ML 相关的性能指标感兴趣?

    在这种情况下,如果您从预训练的检查点初始化您的模型,或者只是通过分配给图中每个变量的给定初始化程序(例如 truncated_normal 或常量)从头开始初始化模型,这无关紧要。

    基本的数学运算将是相同的,主要是矩阵乘法运算,对于他们来说,执行基本的加法和乘法运算的值并不重要。

    这可能有点不同,如果您的图表包含一些更高级的控制流结构,例如 tf.while_loop,这些结构可以根据某些张量的值影响图表的实际大小。

    当然,在程序执行之初初始化图表所需的时间会有所不同,具体取决于您是从头开始初始化还是从检查点初始化。

    希望这会有所帮助。

    【讨论】:

    • 感谢您的回答。是的,我现在只对运行时感兴趣。
    猜你喜欢
    • 2019-05-04
    • 2018-10-04
    • 2017-06-16
    • 2019-07-29
    • 2018-06-27
    • 1970-01-01
    • 2017-04-13
    • 1970-01-01
    • 2019-07-18
    相关资源
    最近更新 更多