如何将大量数据加载到内存中"in advance"以避免从磁盘读取?



我正在直接使用笔记本电脑的GPU(GeForce GTX 1050)在一些自定义图像数据集上训练ConvNet(Keras,python)。在训练期间监控我的 GPU 时,我注意到它只使用了大约 10% 的容量,甚至更少。进一步的调查使我了解到,通过访问存储磁盘中的数据(我正在使用数据生成器),培训遇到了瓶颈。

我还注意到,虽然磁盘以 100% 的容量使用,但我的内存却没有(大约 65% 的使用率)。我教:让我们在GPU训练当前批次时">提前"将下一批数据(或下几批)加载到内存中,然后从内存直接访问加载的批次,避免昂贵的磁盘读取。我在堆栈溢出和其他平台上寻找了一些文档或代码,但没有找到任何相关内容。

我发现避免此磁盘读取瓶颈的一种临时解决方案是将数据粘贴到我的操作系统磁盘上,这是一个 SSD。它的效果非常好,将训练时间减少了 10-15 倍。但是由于我在 SSD 磁盘上的存储容量有限 (100 Gb),当我使用较重的数据时,此解决方案将不起作用(通常,我现在使用重新采样的图像 (64, 64),但我计划升级到 (128, 128) 甚至更多)。

下面是我的生成器的代码,这样你就可以更好地了解情况:

def generator(self, passes=np.inf):
# initialize the epoch count
db = self.db
epochs = 0
# keep looping infinitely -- the model will stop once we have
# reach the desired number of epochs
while epochs < passes:
# shuffle dataset_indices for stochasticity
if self.shuffle == True: np.random.shuffle(self.dataset_indices)
# loop over the HDF5 dataset_indices
for i in np.arange(0, self.numImages, self.batchSize):
X, Y = [], []
if self.gaussian_test == True:  # TODO : Add gaussian testing
for j in self.dataset_indices[i:i + self.batchSize]:
y = db[db[self.gen_type + "_indices"][j]]["label"][()]
X.append(np.random.normal(loc=y, scale=0.2, size=(1, 64, 64)))
Y.append(y)
else:
for j in self.dataset_indices[i:i + self.batchSize]:
X.append(db[db[self.gen_type + "_indices"][j]]["array"][()])
Y.append(db[db[self.gen_type + "_indices"][j]]["label"][()])
X = np.array(X)
Y = np.array(Y)
Y = to_categorical(Y, num_classes=6)
# yield a tuple of images and labels
yield (X, Y)
# increment the total number of epochs
epochs += 1

我不确定如何进行,但我很确定这应该是可能的......

由于我现在没有收到任何答案,我正在为任何对该主题感兴趣的人分享我的发现。实际上,我一直在寻找的想法是使用多处理...

(I):经过一些研究,我发现 Kerasfit_generator()允许通过参数use_multiprocessing = Trueworker = n进行这种多处理。但是这种方法有其局限性:

  • 首先,您的生成器必须是线程安全的。如果你的生成器继承自 Keras.utils.Sequence 类,它已经是线程安全的。或者,请参阅本教程,您将在其中学习如何创建一个装饰器,使您的生成器线程安全。
  • 其次,如果您使用的是 Windows 计算机,则无法设置use_multiprocessing = True,因为它未实现。虽然,我意识到您仍然可以将worker = n 设置为 1>但我认为您的生成器不会是线程安全的,这是一个问题。

(II) :由于我使用的是Windows计算机,这对我不起作用。然后我找到了其他资源(TensorFlow doc,博客文章)建议使用TensorFlow QueueRunner 类。这似乎是最有效和最强大的解决方案,但你需要使用TensorFlow,如果你第一次深入研究它,这可能会很耗时。我还没有尝试过这个解决方案,因为我预计在未来几天内迁移到 AWS 云,因此允许我使用第一个解决方案。

最新更新