多个队列导致TF锁定

时间:2016-02-15 16:12:37

标签: tensorflow

我正在尝试使用多个队列进行读取和批处理,但这会导致TF偶尔锁定。这是一些示例代码:

import tensorflow as tf

coordinator = tf.train.Coordinator()

file_queue = tf.train.string_input_producer(tf.train.match_filenames_once(...))
reader = tf.TextLineReader()
key, serialized_example = reader.read(file_queue)
keys, serialized_examples = tf.train.batch([key, serialized_example], 10)

# repeat the code snippet below multiple times, in my case 4
file_queue_i = tf.train.string_input_producer(tf.train.match_filenames_once(...))
reader_i = tf.TextLineReader()
key_i, serialized_example_i = reader.read(file_queue_i)

initializer = tf.initialize_all_variables()

session = tf.Session(config=tf.ConfigProto(inter_op_parallelism_threads=1, intra_op_parallelism_threads=1))
session.run(initializer)

threads = tf.train.start_queue_runners(sess=session, coord=coordinator)

session.run(keys)

TensorFlow偶尔锁定在最后一行,当我实际尝试运行某些东西时。但是,使用上面的代码很难重现这种行为。在1000多次运行中,我只能挂起一次。在我的真实代码中,实际的读者更复杂,它使用的是TFRecords,但其他方面都是一样的。它有2/3的时间挂起,共有3个队列。有5个队列,它似乎永远不会运行,并且有一个队列,它似乎永远不会挂起。这是在0.6的Mac上。我有一个不同的系统运行Ubuntu,也有0.6,我遇到了同样的问题(虽然在Ubuntu系统上锁定的频率要高得多)。

更新:对上述代码锁定频率的更准确估计是5,000次试验中的1次。

1 个答案:

答案 0 :(得分:2)

这可能是由于没有足够的操作线程造成的。如果你有一个队列运行器1取决于队列运行器2的工作,并且你以异步方式运行它们,那么你需要至少两个操作线程,通过inter_op_parallelism_threads设置,以保证正在取得进展。

在您的情况下,您的队列运行符正在填充batch线程,具体取决于string_input_producer队列不为空。如果与string_input_producer队列关联的队列运行器首先运行,那么一切都很好。但是如果首先调度batch队列运行器,它将卡在string_input_producer.dequeue op中,等待string_input_producer队列获取一些文件名。由于TensorFlow操作线程池中只有1个线程,enqueue的{​​{1}}操作永远不会被分配一个线程来完成(即执行其string_input_producer方法)

最简单的解决方案是至少拥有与同时Compute调用一样多的操作线程(即队列数+ 1)。如果您真的想限制自己使用一个线程,可以使用主线程同步预加载文件名队列文件文件名。

run

如果您有多个文件名队列,则上面的代码需要一些封装。或者,如果所有input_producer队列都有 coordinator = tf.train.Coordinator() import glob files = glob.glob('/temp/pipeline/*') if FLAGS.preload_filenames: file_queue = tf.FIFOQueue(capacity=len(files), dtypes=tf.string) enqueue_val = tf.placeholder(dtype=tf.string) enqueue_op = file_queue.enqueue(enqueue_val) else: file_queue = tf.train.string_input_producer(files) reader = tf.TextLineReader() key, serialized_example = reader.read(file_queue) keys, serialized_examples = tf.train.batch([key, serialized_example], 5, capacity=10) initializer = tf.initialize_all_variables() session = tf.Session(config=tf.ConfigProto(inter_op_parallelism_threads=1, intra_op_parallelism_threads=1)) print 'running initializer' session.run(initializer) if FLAGS.preload_filenames: print 'preloading filenames' for fn in files: session.run([enqueue_op], feed_dict={enqueue_val: fn}) print 'size - ', session.run([file_queue.size()]) session.run([file_queue.close()]) print 'starting queue runners' threads = tf.train.start_queue_runners(sess=session, coord=coordinator) print 'about to run session' print session.run(keys) 个文件名

,那么这是一个hacky解决方案应该可行的。
prebuffer_amount