我注意到,对于我尝试运行的模型,我的 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 使用预取根本不会影响性能?感谢您的任何建议。
最佳答案
如果您的 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
更灵活的方法, 通过显式复制到 GPU tf.data.experimental.copy_to_device(...)
然后预取。这可以避免 prefetch_to_device
的限制。必须是管道中的最后一个转换,并允许结合进一步的技巧来优化 Dataset
管道性能(例如通过实验 overriding threadpool distribution )。 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/1x Tesla P100/Inception V3/ImageNet 样本/32-batch)
关于tensorflow - tf.contrib.data.prefetch_to_device 不会导致训练加速,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53711742/