让我首先发出警告:
大多数人以错误的方式完成了神经网络的正确基准测试。对于 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)
它所做的只是创建一个常量张量并应用一个全连接层。
一切运营放置在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
通过您的网络。如果你接受使用 python 的开销time
包,你就完成了。
但不幸的是,这并不是故事的全部。
将结果从张量操作复制回来'fc/BiasAdd:0'
访问设备内存(GPU)并复制到主机内存(CPU、RAM)。
因此,在某些时候 PCI 带宽会受到限制。某个地方也有一个 python 解释器,占用 CPU 周期。
此外,运营放置在 GPU 上,不需要values他们自己。不确定您使用的是哪个 TF 版本。但即使是一个tf.const
不保证旧版本中会放置在 GPU 上。我只是在编写自己的操作时才注意到这一点。顺便说一句:请参阅我的其他答案TF 如何决定在哪里开展业务.
现在,最困难的部分是:这取决于你的图表。有一个tf.cond/tf.where
坐在某个地方会让事情变得更难进行基准测试。现在,您需要经历在有效训练深度网络时需要解决的所有这些困难。这意味着,一个简单的 const 无法解决所有情况。
解决方案首先将/staging一些价值观directly通过运行进入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性能指南