我注意到,在尝试运行的模型中,我的GPU利用率仅为30%左右,并且由于I / O,这30%的利用率经常会交替使用0%的利用率。为了解决I / O,我在代码中添加了tf.contrib.data.prefetch_to_device
,如下所示:
dataset = tf.data.TFRecordDataset(self.filenames, "ZLIB", 384 * 1024 * 1024)
dataset = dataset.map(parse_func, 6)
dataset = dataset.prefetch(6)
dataset = dataset.apply(tf.contrib.data.prefetch_to_device("/gpu:0", 12))
#dataset = dataset.apply(tf.contrib.data.prefetch_to_device("/gpu:0", 2))
#dataset = dataset.apply(tf.contrib.data.prefetch_to_device("/gpu:0", 6))
self.iterator = dataset.make_initializable_iterator()
如您所见,我在尝试解决此问题时做了一些事情,包括:
buffer_size
参数(对时间没有影响:我尝试了12、6、2和1)dataset.prefetch
行,以防它以某种方式干扰设备级的预取(我也尝试使用较小的数字,例如2和1)当我安排训练时间时,在这些变化中没有看到有意义的差异。同样,GPU利用率继续遵循相同的模式,即利用率交替为0%和30%。我还应该尝试什么?为什么对GPU进行预取根本不影响性能?感谢您的任何建议。
答案 0 :(得分:0)
如果您的CPU和GPU均在<100%,则您的I / O很可能是瓶颈。尝试使用更大的批处理大小来优化进出GPU的I / O,但会增加内存负载。将数据预提取到GPU应该可以通过将数据的预处理与下游计算重叠来解决此问题。除此之外,您可能还需要考虑监视光盘负载,并查看其是否饱和。从任何类型的远程主机流式传输数据时,网络I / O(例如例如)也可能是一个问题(例如从AWS S3或GC存储存储桶中传输TFRecords)。
如果您的CPU约为100%,而GPU为<100%,那么您的CPU就是瓶颈。如果您在云上,请考虑移至CPU数量较大的实例( CPU便宜,GPU稀缺)。如果您无法增加CPU数量,则可以将图形的某些部分移至GPU。但是,TF的Dataset
管道完全在CPU上运行(尽管see)。 预取在这里也可能有帮助,但是生成另一个后台线程以填充缓冲区以供下游使用的代价可能会减弱此效果。另一种选择是脱机执行某些或所有预处理步骤(在训练之前即)。
预取。
prefetch_to_device
更灵活的方法,方法是使用tf.data.experimental.copy_to_device(...)
显式复制到GPU,然后进行预取。这样可以避免prefetch_to_device
必须是管道中的最后一个转换的限制,并允许结合其他技巧来优化Dataset
管道的性能(通过实验{{ 3}})。tf.contrib.data.AUTOTUNE
选项进行预取,该方法允许tf.data
运行时根据您的系统和环境自动调整预取缓冲区的大小。最后,您可能最终会执行以下操作:
dataset = dataset.apply(tf.data.experimental.copy_to_device("/gpu:0"))
dataset = dataset.prefetch(tf.contrib.data.AUTOTUNE)
性能比较。
( 8个CPU / 1个Tesla P100 / Inception V3 / ImageNet示例/ 32批)
答案 1 :(得分:0)
在我的实验中,我观察到prefetch()
之前没有CPU prefetch_to_device()
(即使缓冲区大小为1)且仅使用可初始化的迭代器而不是一个快照迭代器时,速度略有提高。但是,结合上游Keras 2.2.4(+ TF 1.13),我仍然没有在nvprof可视化中观察到完全重叠的memcpy。我的假设是Keras中存在一些问题。