10、数据读取(二)——队列管理器和协程协调器实现异步读取训练
分析: 当数据量很大时,入队操作从硬盘中读取数据,放入内存中,主线程需要等待入队操作完成,才能进行训练。会话里可以运行多个.线程,实现异步读取。
1、队列管理器 API
(1) tf.train.QueueRunner(queue, enqueue_ ops=None)
创建一个QueueRunner
● queue: A Queue 定义的队列,指定子线程操作的队列
● enqueue_ops: 添加线程的队列操作列表,[]*2,列表乘以2表示指定两个线程
(2) create_threads(sess, coord=None,start=False):
创建线程来运行给定会话的入队操作
①start: 布尔值,如果True启动线程;如果为False调用者必须调用start()启动线程,
②coord: 线程协调器,后面线程管理需要用到
③return: 线程的实例
通过多线程实现异步,子线程从磁盘读取数据,放入队列,主线程可以直接从队列取数据,不用等子线程将数据全部放入队列主线程才能工作
需求: 子线程: 异步存入样本 主线程: 读取样本
1.定义一个队列,1000个元素
Q = tf.FIFOQueue(1000,tf.float32)
2.定义子线程要做的事情,循环值 +1,放入队列当中
1 var = tf.Variable(1.0) #定义一个变量
2 # data = var + 1 看两个东西是不是一样,只要看二者的op是不是一样,这里不能用简单的+1操作,不然下次再加时还是原来的 var+1,所以要实现一个自增
3 data = tf.assign_add(var, tf.constant(1.0)) #实现一个自增 #assign 分配;指派;[计][数] 赋值
4 en_q = Q.enqueue(data)
3.定义队列管理器op,指定多少个子线程,子线程该干什么事情
1 # tf.train.QueueRunner(Q, enqueue_ops = [en_q, op1, op2, op2, op3] * 4) 列表中的是子线程要做的操作,*4是4个线程 2 # 线程具有随机性,不能被控制(由CPU进行控制),携程可以被控制,所以在列表中的操作4个线程的运行是随机的(即切换随机),不能指定线程运行特定的操作 3 qr = tf.train.QueueRunner(Q, enqueue_ops = [en_q] * 2) #队列管理器,
4、变量初始化
1 init_op = tf.global_variables_initializer()
5、 会话
1 with tf.Session() as sess: 2 #初始化变量 3 sess.run(init_op) 4 # 开启线程管理器 5 coord = tf.train.Coordinator() #coord 线程管理器的老大名字 6 #真正开启子线程 7 threads = qr.create_threads(sess, coord=coord, start=True) 8 #主线程,不断读取数据训练 9 for i in range(300): 10 print(sess.run(Q.dequeue())) 11 #进行回收 12 coord.request_stop() #告诉线程接下来要回收了 13 coord.join(threads) #threads要回收的线程
6、完整代码
1 import tensorflow as tf
2 import os
3 os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' #去掉警告,将警告级别提升
4
5 # 需求: 子线程: 异步存入样本 主线程: 读取样本
6 #
7 # 1.定义一个队列,1000
8 Q = tf.FIFOQueue(1000,tf.float32)
9
10 # 2.定义子线程要做的事情,循环值 +1,放入队列当中
11 var = tf.Variable(1.0) #定义一个变量
12 # data = var + 1 看两个东西是不是一样,只要看二者的op是不是一样,这里不能用简单的+1操作,不然下次再加时还是原来的 var+1,所以要实现一个自增
13 data = tf.assign_add(var, tf.constant(1.0)) #实现一个自增 #assign 分配;指派;[计][数] 赋值
14 en_q = Q.enqueue(data)
15
16 # 3.定义队列管理器op,指定多少个子线程,子线程该干什么事情
17 # tf.train.QueueRunner(Q, enqueue_ops = [en_q, op1, op2, op2, op3] * 4) 列表中的是子线程要做的操作,*4是4个线程
18 # 线程具有随机性,不能被控制(由CPU进行控制),携程可以被控制
19 qr = tf.train.QueueRunner(Q, enqueue_ops = [en_q] * 5)
20
21 # 初始化variables变量op,(变量是一个op)
22 init_op = tf.global_variables_initializer()
23
24 with tf.Session() as sess:
25 #初始化变量
26 sess.run(init_op)
27 # 开启线程管理器
28 coord = tf.train.Coordinator() #coord 线程管理器的老大名字,线程管理器用于管理、回收线程
29 #真正开启子线程
30 threads = qr.create_threads(sess, coord=coord, start=True)
31 #主线程,不断读取数据训练
32 for i in range(1000):
33 print(sess.run(Q.dequeue()))
34 #进行回收
35 coord.request_stop() #告诉线程接下来要回收了
36 coord.join(threads) #threads要回收的线程
输出:
..
..
..
991.0
990.0
992.0
994.0
997.0
997.0
997.0
997.0
998.0
1001.0