我想了解Queue Runners的工作原理。我知道队列运行器用于更有效地填充队列,并行运行几个入队线程。但结果队列是怎样的?究竟发生了什么?
让我更具体地提出我的问题: 我有许多文件,其内容我想放在一个大队列中。
文件1:A,B,C
文件2:D,E,F
文件3:G,H,I
我关注TensorFlow input pipeline。我首先创建一个文件名列表,然后创建一个使用tf.string_input_producer()
的文件名队列,一个阅读器操作和一个解码器。最后,我想将我的序列化示例放入一个可以与图形共享的示例队列中。为此,我使用QueueRunner:
qr = tf.train.QueueRunner(queue, [enqueue_op] * numberOfThreads)
我将它添加到QUEUE_RUNNERS集合中:
tf.train.add_queue_runner(qr)
我的enqueue_op一次排队一个例子。所以,当我使用例如numberOfThreads = 2,结果队列如何?文件以哪种顺序读入队列?例如,队列是否类似于
q = [A, B, C, D, E, F, G, H, I]
(所以尽管并行处理,文件内容没有在队列中混合)
或者队列看起来像是
q = [A, D, B, E, C, F, G, H, I]
?
def get_batch(file_list, batch_size, input_size,
num_enqueuing_threads):
file_queue = tf.train.string_input_producer(file_list)
reader = tf.TFRecordReader()
_, serialized_example = reader.read(file_queue)
sequence_features = {
'inputs': tf.FixedLenSequenceFeature(shape=[input_size],
dtype=tf.float32),
'labels': tf.FixedLenSequenceFeature(shape=[],
dtype=tf.int64)}
_, sequence = tf.parse_single_sequence_example(
serialized_example, sequence_features=sequence_features)
length = tf.shape(sequence['inputs'])[0]
queue = tf.PaddingFIFOQueue(
capacity=1000,
dtypes=[tf.float32, tf.int64, tf.int32],
shapes=[(None, input_size), (None,), ()])
enqueue_ops = [queue.enqueue([sequence['inputs'],
sequence['labels'],
length])] * num_enqueuing_threads
tf.train.add_queue_runner(tf.train.QueueRunner(queue, enqueue_ops))
return queue.dequeue_many(batch_size)
答案 0 :(得分:0)
我实际上发现您提到的同一页面的animated figure非常具有说明性。
有一个第一个队列,即文件名队列,它提供文件读取线程。在每个线程中,文件按顺序读取 - 或者更确切地说,根据读者遵循的顺序读取。这些线程中的每一个都提供另一个队列,即示例队列,其输出将由您的训练消耗。
在您的问题中,您对示例队列中示例的结果顺序感兴趣。
答案取决于读者的工作方式。最佳实践和最有效的方法(在上面的动画图中说明)是在准备好后立即将样本发送到示例队列。此流式传输功能通常由various Reader
variants proposed by tensorflow提供,以促进和简化此最佳做法。但是,当然可以编写一个能够在结束时同时enqueue_many
所有样本的阅读器。
在所有情况下,由于读者处于单独的非同步线程中,因此您无法按其各自输出的顺序进行任何保证。例如,在标准的流式传输案例中,示例可以定期交错,也可以不交错 - 实际上任何事情都可能发生。