Tensorflow数据集预取和缓存选项的正确使用方法是什么



我已经阅读了TF页面和一些关于使用prefetch((和cache((来加速模型输入管道的帖子,并试图在我的数据上实现它。Cache((按预期工作,即在第一个历元中从dist读取数据,在随后的所有历元中,它只是从内存中读取数据。但我在使用prefetch((时遇到了很多困难,我真的不知道何时以及如何使用它。有人能帮我吗?我真的需要一些帮助。我的应用程序是这样的:我有一组大的TFRecord文件,每个文件都包括一些原始记录,在喂网之前需要处理。它们将被混合(不同的样本流(,所以我所做的是:

def read_datasets(pattern, numFiles, numEpochs=125, batchSize=1024, take=dataLength):
files = tf.data.Dataset.list_files(pattern)
def _parse(x):
x = tf.data.TFRecordDataset(x, compression_type='GZIP')
return x
np = 4 # half of the number of CPU cores
dataset = files.interleave(_parse, cycle_length=numFiles, block_length=1, num_parallel_calls=np)
.map(lambda x: parse_tfrecord(x), num_parallel_calls=np)
dataset = dataset.take(take)
dataset = dataset.batch(batchSize)
dataset = dataset.cache()
dataset = dataset.prefetch(buffer_size=10)
dataset = dataset.repeat(numEpochs)
return dataset

interleave函数中的parse_tfrecord(x(函数是将数据应用于模型之前所需的数据预处理,我猜测预处理时间与网络的批处理时间相当。我的整个数据集(包括所有输入文件(包含大约500批1024个样本。我的问题是:

1-如果我进行缓存,我真的需要预取吗?

2-映射、批处理、缓存、预取和重复的顺序正确吗?

3-Tensorflow文档指出,预取的缓冲区大小指的是数据集元素,如果是批处理的,则指批处理的数量。所以在这种情况下,我将阅读10批1024个例子,对吧?我的问题是,通过更改预取缓冲区大小,我看不到运行时间有任何差异,即使将缓冲区大小设置为1000或更大,内存消耗也没有太大变化。

我为斯坦福大学的吴恩达找到了一个很好的解释:https://cs230.stanford.edu/blog/datapipeline/#best-实践

"当GPU在当前批次上进行正向/反向传播时,我们希望CPU处理下一批数据,以便它立即做好准备。作为计算机中最昂贵的部分,我们希望GPU在训练过程中始终得到充分使用。我们称之为消费者/生产者重叠,消费者是GPU,生产者是CPU。

使用tf.data,您可以在管道末端(批处理后(通过对dataset.prefetch(1)的简单调用来实现这一点。这将始终预取一批数据,并确保始终有一批数据准备就绪。

在某些情况下,预取多个批可能很有用。例如,如果预处理的持续时间变化很大,预取10个批次将平均10个批次的处理时间,而不是有时等待更长的批次。

举一个具体的例子,假设10%的批次需要10秒来计算,90%需要1秒。如果GPU在一个批次上训练需要2秒,那么通过预取多个批次,您可以确保我们永远不会等待这些罕见的更长批次">

我不太确定如何确定每批的处理时间,但这是下一步。如果你的批处理花费的时间大致相同,那么我认为预取(batch_size=1(应该足够了,因为你的GPU不会等待CPU完成计算昂贵的批处理。

您能看看这个Stackoverflow答案,快速了解TensorFlow数据集的函数cache()prefetch()吗。

此外,我发现这个Tensorflow文档对优化tf.DataApi的性能非常有帮助。他们为各种执行方式指定了基准和执行时间。您还可以分别找到有关数据的串行化和并行化加载和转换及其执行时间的信息。

相关内容

最新更新