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

 

 

 




posted on 2019-11-15 16:34  Luaser  阅读(208)  评论(0编辑  收藏  举报