【问题标题】:How to load chuncks of data into memory "in advance" to avoid reading from disk?如何“提前”将数据块加载到内存中以避免从磁盘读取?
【发布时间】:2019-06-17 15:49:18
【问题描述】:

我正在使用笔记本电脑的 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


我不确定如何进行,但我很确定应该可以...

【问题讨论】:

    标签: python memory-management data-generation


    【解决方案1】:

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

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

    • 首先,您的生成器必须是线程安全的。如果您的生成器继承自 Keras.utils.Sequence 类,则它已经是线程安全的。否则,请参阅此tutorial,您将在其中学习如何创建一个装饰器,使您的生成器线程安全。
    • 其次,如果你使用的是Windows电脑,那么你不能设置use_multiprocessing = True,因为它没有实现。虽然,我意识到你仍然可以设置 workers = n > 1 但是我认为你的生成器不会是线程安全的,这是一个问题。

    (II) : 因为我使用的是 Windows 计算机,所以这对我不起作用。然后我发现其他资源(TensorFlow docBlog post)建议使用 TensorFlow QueueRunner 类。这似乎是最有效和最强大的解决方案,但您需要使用 TensorFlow,如果您必须第一次深入了解它,这可能会很耗时。我还没有尝试过这个解决方案,因为我预计在未来几天内会迁移到 AWS 云,因此我可以使用第一个解决方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-16
      • 1970-01-01
      • 1970-01-01
      • 2018-08-03
      • 2013-06-10
      • 2012-10-12
      • 2016-03-16
      • 2012-02-24
      相关资源
      最近更新 更多