我使用Tensorflow评估不同的图像分类模型,特别是使用不同设备的推理时间。 我想知道是否必须使用预训练模型。 我使用一个脚本生成1000个随机输入图像,逐个将它们送入网络,并计算平均推断时间。
谢谢!
答案 0 :(得分:3)
首先我要警告:
大多数人以错误的方式对神经网络进行适当的基准测试。对于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
包的开销,那么就完成了。
但不幸的是,这不是整个故事。
将结果从张量操作'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
答案 1 :(得分:0)
那么,为了澄清一下,您只对每个推理步骤的运行时感兴趣,而不是对准确度或任何与ML相关的性能指标感兴趣?
在这种情况下,如果从预训练检查点初始化模型,或者只是从头开始,通过分配给图中每个变量的给定初始值设定项(例如truncated_normal或constant),则无关紧要。
基础数学运算将是相同的,主要是矩阵乘法运算,对它们来说无关紧要(更多)执行基础加法和乘法运算的值。
如果您的图形包含一些更高级的控制流结构(如tf.while_loop),可能会影响图形的实际大小,具体取决于某些张量的值,这可能会略有不同。
当然,在程序执行开始时初始化图形所需的时间将根据您是从头开始还是从检查点初始化而有所不同。
希望这有帮助。