tf.contrib.data.prefetch_to_device 不会导致训练加速

TFd*_*doe 5 io gpu prefetch tensorflow

我注意到,对于我尝试运行的模型,我的 GPU 利用率仅为 30% 左右,而且通常由于 I/O,30% 的利用率会与 0% 利用率交替出现。为了解决添加到我的代码中的 I/OI,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()
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我在尝试解决此问题时做了一些事情,包括:

  • 改变buffer_size参数(对时间没有影响:我尝试了 12、6、2 和 1)
  • 是否在其他 GPU 上并行运行其他作业。在任何一种情况下都不会影响训练时间
  • 消除该dataset.prefetch行,以防它以某种方式干扰设备级预取(我也尝试了较小的数字,例如 2 和 1)

当我为训练计时时,我没有发现这些变化有任何有意义的差异。此外,GPU 利用率继续遵循相同的模式,交替使用 0% 和 30% 的利用率。我还应该尝试什么?为什么使用 GPU 预取根本不会影响性能?感谢您的任何建议。

Ala*_*off 7

如果您的 CPU 和 GPU 均 <100%,则您的 I/O 很可能是瓶颈。尝试使用更大的批量大小来优化 GPU 的 I/O,但代价是更大的内存负载。通过将数据预处理与下游计算重叠,将批次预取到 GPU 应该有助于解决这个问题。除此之外,您可能还需要考虑监视磁盘负载,并查看它是否已饱和。网络 I/O,例如从任何类型的远程主机流式传输数据时,也可能是一个问题(例如从 AWS S3 或 GC 存储桶流式传输 TFRecord)。

如果您的 CPU 约为 100%,而 GPU <100%,则您的 CPU 是瓶颈。如果您在云上,请考虑迁移到具有更大 CPU 数量的实例(CPU 便宜,GPU 稀缺)。如果您无法增加 CPU 数量,可以选择将图形的某些部分移至 GPU。然而,TF 的Dataset管道完全在 CPU 上运行(尽管如此,请参阅 参考资料)。预取在这里也可能有所帮助,但是生成另一个后台线程来填充下游缓冲区的成本可能会削弱这种效果。另一种选择是离线执行部分或全部预处理步骤(在训练之前)。

预取

  • 考虑使用比 更灵活的方法prefetch_to_device,通过显式复制到 GPU tf.data.experimental.copy_to_device(...),然后预取。这允许避免prefetch_to_device必须是管道中最后一个转换的限制,并允许结合更多技巧来优化Dataset管道性能(例如,通过实验性覆盖线程池分布)。
  • 尝试tf.contrib.data.AUTOTUNE预取的实验选项,它允许tf.data运行时根据您的系统和环境自动调整预取缓冲区大小。

最后,你可能会做这样的事情:

dataset = dataset.apply(tf.data.experimental.copy_to_device("/gpu:0"))
dataset = dataset.prefetch(tf.contrib.data.AUTOTUNE)
Run Code Online (Sandbox Code Playgroud)

性能比较

8 个 CPU / 1x Tesla P100 / Inception V3 / ImageNet 样本 / 32 批次

在此输入图像描述