我用数据集 API 方法替换了项目中的 CIFAR-10 预处理管道,它导致性能下降约 10-20%。
预处理是相当标准的:
- 从磁盘读取图像
- 随机/裁剪和翻转
- 洗牌,批量
- 喂给模型
总的来说,我看到批处理现在快了 15%,但每隔一段时间(或者,更准确地说,每当我重新初始化数据帧或期望重新洗牌)批处理被阻塞很长时间(30 秒),这总共是一个较慢的时代-per-epoch 处理。
这种行为似乎与内部散列有关。如果我在 ds.shuffle(buffer_size=N) 中减少 N,延迟会更短,但按比例更频繁。完全删除 shuffle 导致延迟,就像将 buffer_size 设置为数据集大小一样。
有人可以解释数据集 API 在读取/缓存方面的内部逻辑吗?是否有任何理由期望数据集 API 的工作速度比手动创建的队列更快?
我正在使用 TF 1.3。
最佳答案
如果您实现 同 使用 tf.data.Dataset
的管道API 和使用队列,Dataset 版本的性能应该优于基于队列的版本。
但是,为了获得最佳性能,需要遵守一些性能最佳实践。我们已将这些收集在 performance guide for tf.data
中.以下是主要问题:
dataset.prefetch(1)
到您的管道末尾将为您提供预取的大部分好处,但您可能需要进一步调整它。dataset.repeat(NUM_EPOCHS).shuffle(N)
.相比之下,你也可以写dataset.shuffle(N).repeat(NUM_EPOCHS)
,但这需要在每个时期重新开始洗牌。后一种方法稍微更可取(例如,更符合 SGD 的定义),但如果您的数据集很大,则差异可能不明显。我们正在添加一个不会导致延迟的融合版本的 shuffle-and-repeat,并且每晚构建的 TensorFlow 将包含自定义
tf.contrib.data.shuffle_and_repeat()
等效于 dataset.shuffle(N).repeat(NUM_EPOCHS)
的转换但不会在每个时代开始时受到延迟。话虽如此,如果您的管道在使用
tf.data
时明显变慢了比队列,请提交 GitHub issue详细信息,我们来看看!
关于performance - Tensorflow 数据集 API 是否比队列慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47403407/