队列和线程

  和 TensorFlow 中的其他组件一样,队列(queue)本身也是图中的一个节点,是一种有状态的节点,其他节点,如入队节点(enqueue)和出队节点(dequeue),可以修改它的内容。例如,入队节点可以把新元素插到队列末尾,出队节点可以把队列前面的元素删除。本节主要介绍队列、队列管理器、线程和协调器的有关知识。

1、队列:

  TensorFlow 中主要有两种队列,即 FIFOQueue 和 RandomShuffleQueue,它们的源代码实现在 tensorflow-1.1.0/tensorflow/python/ops/data_flow_ops.py 中。

  (1)、FIFOQueue

   FIFOQueue创建一个先入先出队列。列如,我们在训练一些语音、文字样本时,使用循环神经网络的网络结构,希望读入的训练样本是有序的,就要用FIFOQUEUE。

  我们行创建一个含有队列的图:

 # -*- coding: UTF-8 -*-
# date:2018/6/22
# User:WangHong
import tensorflow as tf
#创建一个先入先出的队列,初始化队列插入0.1,0.2,0.3三个数字
q = tf.FIFOQueue(3,'float')
init = q.enqueue_many(([0.1,0.2,0.3],))
#定义出队、+1、入队操作
x =q.dequeue()
y = x+1
q_inc = q.enqueue([y])
#然后开启一个会话,执行2次q_inc操作,随后查看队列内容。
with tf.Session() as sess:
sess.run(init)
quelen = sess.run(q.size())
for i in range(2):
sess.run(q_inc)#执行2次操作,队列中的值变为0.3,1.1,1.2
quelen = sess.run(q.size())
for i in range(quelen):
print(sess.run(q.dequeue()))#输出队列的值

结果:

     

  (2)、RandomShuffleQueue

    RandomShuffleQueue创建一个随机队列,在出队列时,是以随机的顺序产生元素的,例如,我们在训练一些图像样本是,使用CNN的网络结构,希望。可以无序的读入训练样本,就要用RandomShuffleQueue,每次随机产生一个训练样本。

    RandomShuffleQueue在在TensorFlow使用异步计算时很重要。因为TensorFlow的会话是支持多线程的,我们可以在主线程里执行训练操作,使用RandomShuffleQueue作为训练输入,开多线程来准备训练样本,将样本压入队列后,主线性会从线程中每次取出mini-batch的样本进行训练。

例子;

 # -*- coding: UTF-8 -*-
# date:2018/6/22
# User:WangHong
import tensorflow as tf
q = tf.RandomShuffleQueue(capacity=10,min_after_dequeue=2,dtypes = 'float')
#然后开启一个会话
sess = tf.Session()
for i in range(0,10):#10次入队
sess.run(q.enqueue(i))
for i in range(0,8):#8次出队
print(sess.run(q.dequeue()))

结果:发现结果是乱序

     

我们尝试修改入队次数为 12 次,再运行,发现程序阻断不动,或者我们尝试修改出队此
时为 10 次,即不保留队列最小长度,发现队列输出 8 次结果后,在终端仍然阻断了。

阻断一般发生在:
● 队列长度等于最小值,执行出队操作;
● 队列长度等于最大值,执行入队操作。

  上面的例子都是在会话的主线程中进行入队操作。当数据量很大时,入队操作从硬盘中读
取数据,放入内存中,主线程需要等待入队操作完成,才能进行训练操作。会话中可以运行多
个线程,我们使用线程管理器 QueueRunner 创建一系列的新线程进行入队操作,让主线程继续
使用数据,即训练网络和读取数据是异步的,主线程在训练网络,另一个线程在将数据从硬盘
读入内存。

 2、队列管理器

  创建一个含有队列的图:

 # -*- coding: UTF-8 -*-
# date:2018/6/22
# User:WangHong
import tensorflow as tf
q = tf.FIFOQueue(1000,'float')
counter = tf.Variable(0.0)#计数器
increment_op = tf.assign_add(counter,tf.constant(1.0))#操作给计数器加一
enqueue_op = q.enqueue(counter)#操作;计数器值加入队列
#创建UI个队列计数器QueueRunner,用这两个操作向队列q添加元素。目前使用一个线程
qr = tf.train.QueueRunner(q,enqueue_ops=[increment_op,enqueue_op]*1)
#启动一个会话,从队列管理器qr中创建线程:
#主线程
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
enqueue_threads = qr.create_threads(sess,start=True)#启动入队线程
for i in range(10):
print(sess.run(q.dequeue()))

结果:

     

  

  不是我们期待的自然数列,并且线程被阻断。这是因为加 1 操作和入队操作不同步,可能
加 1 操作执行了很多次之后,才会进行一次入队操作。另外,因为主线程的训练(出队操作)
和读取数据的线程的训练(入队操作)是异步的,主线程会一直等待数据送入。

  QueueRunner 有一个问题就是:入队线程自顾自地执行,在需要的出队操作完成之后,程
序没法结束。这样就要使用 tf.train.Coordinator 来实现线程间的同步,终止其他线程。

 3、线程协调器

 # -*- coding: UTF-8 -*-
# date:2018/6/22
# User:WangHong
import tensorflow as tf
q = tf.FIFOQueue(1000,'float')
counter = tf.Variable(0.0)#计数器
increment_op = tf.assign_add(counter,tf.constant(1.0))#操作给计数器加一
enqueue_op = q.enqueue(counter)#操作;计数器值加入队列
#创建UI个队列计数器QueueRunner,用这两个操作向队列q添加元素。目前使用一个线程
qr = tf.train.QueueRunner(q,enqueue_ops=[increment_op,enqueue_op]*1)
#启动一个会话,从队列管理器qr中创建线程:
#主线程
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
coord = tf.train.Coordinator()
enqueue_threads = qr.create_threads(sess,start=True)#启动入队线程
coord.request_stop() # 通知其他线程关闭
for i in range(10):
try:
print(sess.run(q.dequeue()))
except tf.errors.OutOfRangeError:
break
coord.join(enqueue_threads)#join操作等待其他线程结束,其他所有线程关闭之后,这一函数才能返回

所有队列管理器被默认加在图的 tf.GraphKeys.QUEUE_RUNNERS 集合中。

6、TensorFlow基础(四)队列和线程的更多相关文章

  1. python队列、线程、进程、协程

    目录: 一.queue 二.线程 基本使用 线程锁 自定义线程池 生产者消费者模型(队列) 三.进程 基本使用 进程锁 进程数据共享 默认数据不共享 queues array Manager.dict ...

  2. python队列、线程、进程、协程(转)

    原文地址: http://www.cnblogs.com/wangqiaomei/p/5682669.html 一.queue 二.线程 #基本使用 #线程锁 #自定义线程池 #生产者消费者模型(队列 ...

  3. 四种Java线程池用法解析

    本文为大家分析四种Java线程池用法,供大家参考,具体内容如下 http://www.jb51.net/article/81843.htm 1.new Thread的弊端 执行一个异步任务你还只是如下 ...

  4. MIT 2012分布式课程基础源码解析-线程池实现

    主要内容 ScopedLock 队列实现 线程池实现 在正式讲解线程池实现之前,先讲解两个有用的工具类: ScopedLock fifo队列 ScopedLock: ScopedLock是局域锁的实现 ...

  5. Android系统--输入系统(十四)Dispatcher线程情景分析_dispatch前处理

    Android系统--输入系统(十四)Dispatcher线程情景分析_dispatch前处理 1. 回顾 我们知道Android输入系统是Reader线程通过驱动程序得到上报的输入事件,还要经过处理 ...

  6. (四)juc线程高级特性——线程池 / 线程调度 / ForkJoinPool

    13. 线程池 第四种获取线程的方法:线程池,一个 ExecutorService,它使用可能的几个池线程之一执行每个提交的任务,通常使用 Executors 工厂方法配置. 线程池可以解决两个不同问 ...

  7. “全栈2019”Java多线程第十四章:线程与堆栈详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  8. 【Java并发】并发队列与线程池

    并发队列 阻塞队列与非阻塞队 ConcurrentLinkedQueue BlockingQueue ArrayBlockingQueue LinkedBlockingQueue PriorityBl ...

  9. 【CUDA 基础】5.6 线程束洗牌指令

    title: [CUDA 基础]5.6 线程束洗牌指令 categories: - CUDA - Freshman tags: - 线程束洗牌指令 toc: true date: 2018-06-06 ...

随机推荐

  1. python类和元类

    python 类和元类详解  小麦麦子 2016-09-06 11:11:00        今天在网上看到一篇关于python语言中类和元类(metaclass)的一些讲解和简单运用,感觉对pyth ...

  2. 微交互:App成功的秘诀

    以下内容由Mockplus团队翻译整理,仅供学习交流,Mockplus是更快更简单的原型设计工具. 最好的产品拥有两个很棒的特点:功能和细节.产品的功能可成功吸引到人们的注意力,而产品的细节则可留住你 ...

  3. velocity在html中换行符转换

    <td colspan="3" class="tdContent2">$!obj.getDealInfo().replaceAll("\r ...

  4. http://angular.github.io/router/

    Angular New Router Guide Configuring the Router- This guide shows the many ways to map URLs to compo ...

  5. 马婕 2014MBA专硕考试 报刊选读 7 美国的欧洲时刻(转)

    http://blog.sina.com.cn/s/blog_3e66af46010170ma.html America's European moment美国的欧洲时刻 The troubling ...

  6. Rhino 使 JavaScript 应用程序更灵动(转载)

    脚本语言有良好的快速开发,高效率的执行,解释而非编译执行等优点,并且具有与其他语言编写的组件之间强大的通信功能.JavaScript 一直是脚本语言中的领头羊,它是一门具有非常丰富特性的语言.除了浏览 ...

  7. Zend_Application 流程详解

    本周没什么工作,zend 系统性的东西渐渐忘记,抽时间整理一下代码!Zend_Application 负责加载配置以及初始化资源,所以index.php 会有这行代码 /** Zend_Applica ...

  8. [美国代购] Nexus 6 与 Moto X 询价聊天记录整理

    目前手上使用的是 Mi 3,使用了根本还不到一年,但是发现非常多的问题. 官方 APP 不能卸载: 手机的顶部(摄像头)处经常出现高温度现象,如果你长时间讲电话,那么这个温度真的可以烫到你的耳朵无法承 ...

  9. Postgres的TOAST技术

    一.介绍 首先,Toast是一个名字缩写,全写是The OverSized Attribute Storage Technique,即超尺寸字段存储技术,顾名思义,是说超长字段在Postgres的一个 ...

  10. WP8.1StoreApp(WP8.1RT)---MessageBox与MessageDialog

    在WP7和WP8中,MessageBox是跟WinForm中一样常用的对话框,但是有一个显著的缺点,就是WP7/8中默认的MessageBox是阻塞线程的.也许是由于这个原因,WP8.1/Win8中采 ...