【问题标题】:How does one move data to multiple GPU towers using Tensorflow's Dataset API如何使用 Tensorflow 的 Dataset API 将数据移动到多个 GPU 塔
【发布时间】:2018-04-08 11:20:08
【问题描述】:

我们正在 Tensorflow 上运行多 GPU 作业,并评估从基于队列的模型(使用 string_input_producer 接口)到新的 Tensorflow 数据集 API 的迁移。后者似乎提供了一种更简单的方式来同时在训练和验证之间切换。

下面的一段代码显示了我们是如何做到这一点的。

    train_dataset, train_iterator = get_dataset(train_files, batch_size, epochs)
    val_dataset, val_iterator = get_dataset(val_files, batch_size, epochs)


    is_validating = tf.placeholder(dtype=bool, shape=())
    next_batch = tf.cond(is_validating,
               lambda: val_iterator.get_next(),
               lambda: train_iterator.get_next())

    validation_tower = self.num_gpus - 1
    tower_grads = []

    for i in range(self.num_gpus):
        with tf.variable_scope(tf.get_variable_scope(),reuse=(i > 0)):
            with tf.device('/gpu:%d' % i), tf.name_scope('%s_%d' % ('gpu_', i)) as scope:
                if i == validation_tower:
                    images, labels = next_batch
                    # Loss funcs snipped out
                else:
                    images, labels = next_batch
                    # Loss funcs snipped out

get_dataset 函数构建数据集,设置映射函数和批量大小。它还构建了一个迭代器,但不初始化它。迭代器的初始化发生在会话开始之前。

is_validating 布尔值在会话运行时提供,每隔几步我们通过 feed_dict 将 is_validating 传递为 True 以使用验证数据集

我的问题是:

假设我有 8 个 GPU,所以我们在 7 个 GPU 上运行训练。迭代器是否从这 7 个 GPU 中的每一个的相同点前进,从而为所有 7 个 GPU 提供相同的数据?

【问题讨论】:

    标签: tensorflow tensorflow-gpu tensorflow-datasets


    【解决方案1】:

    目前主要有三个选项,它们具有不同的可用性和性能权衡:

    1. Dataset.batch() 转换中,创建一个包含所有 GPU 示例的大批量。然后在Iterator.get_next() 的输出上使用tf.split(..., self.num_gpus) 为每个GPU 创建子批次。这可能是最简单的方法,但它确实将拆分置于关键路径上。

    2. Dataset.batch() 转换中,创建一个适合单个 GPU 大小的小批量。然后每个 GPU 调用一次Iterator.get_next() 以获得多个不同的批次。 (相比之下,在您当前的代码中,next_batch 的相同值被发送到每个 GPU,这可能不是您想要发生的。)

    3. 创建多个迭代器,每个 GPU 一个。在管道的早期使用Dataset.shard() 对数据进行分片(例如,如果您的数据集被分片,则在文件列表中)。请注意,这种方法会消耗主机上的更多资源,因此您可能需要调低任何缓冲区大小和/或并行度

    请注意,当前的tf.data 流水线仅在 CPU 上运行,高效流水线的一个重要方面是在上一步仍在运行时将您的训练输入暂存到 GPU。请参阅 TensorFlow CNN benchmarks 示例代码,该代码展示了如何有效地将数据暂存到 GPU。我们目前正在努力将此支持直接添加到tf.data API。

    【讨论】:

    • 谢谢,@mrry!非常有帮助和详细。还有一个问题要问你:在我们当前的基于队列的方法 (tf.train.string_input_producer) 中,每个 GPU 都有一个队列,每个队列都有整个数据集的副本。每个队列都被打乱,作业在数据集上无限运行固定数量的步骤。我们类似地尝试了 Dataset, Iterator per GPU 方法并且它有效。但是,我们注意到的主要区别是处理的示例数量。在前者中,我们每秒处理大约 200 个示例,而在后者中大约 20 个,因此吞吐量降低了 10 倍(续..)
    • 这是因为 string_input_producers 本身在 GPU 上运行吗?是否有可以实现这种吞吐量的数据集、迭代器方法?对我们当前方法的任何其他建议也会有所帮助。
    • 我正在尝试将此解决方案实施到基准代码中,但这似乎不是因为 tf.Dataset 而是因为获取数据的线程。我唯一改变的是 minibatch 函数中的 tf.cond 但代码永远卡在 self.cond.wait()
    猜你喜欢
    • 2019-09-24
    • 2018-03-03
    • 2018-04-14
    • 2018-01-02
    • 2013-07-21
    • 2019-11-15
    • 2018-07-06
    • 2019-01-01
    • 1970-01-01
    相关资源
    最近更新 更多