首页 > 编程语言 >tensorflow1.x——如何在python多线程中调用同一个session会话

tensorflow1.x——如何在python多线程中调用同一个session会话

时间:2022-11-16 19:05:06浏览次数:65  
标签:__ sess tensorflow1 thread python session tf 多线程

如何在python多线程中调用同一个session会话?

 

这个问题源于我在看的一个强化学习代码:

​https://gitee.com/devilmaycry812839668/scalable_agent​

 

在众多的机器学习的分支中,凡是使用深度学习模型的基本都不会考虑本文的这个问题,不论是监督学习还是非监督学习,其学习过程都可以使用串行计算的算法逻辑来解决,但是唯独强化学习是个例外。

强化学习可以使用串行方式计算,但是由于其有采样这个操作并且采样效率还比较低下,因此在强化学习的并行采样中就出现了本文的这个问题,或者更具体的是说在一个进程的多个线程中是否可以调用同一个session,这个主进程可以是C++的也可以是python的,这个session可以是TensorFlow的同样也可以是pytorch的,为了不过大扩张本文的讨论范围,本文的设定是只讨论python下多线程对TensorFlow的同一个session会话的调用情况,不过也计划在本文后再做一个C++下多进程对TensorFlow同一个session会话的调用情况研究。

 

 

---------------------------------------

 

 

先从一个外网的poster来看这个问题:

 

[英] Reusing Tensorflow session in multiple threads causes crash(在多个线程中重用Tensorflow会话会导致崩溃)(中文翻译版本)

上文同样是从强化学习的应用背景出发,原文作者给出了一个python多线程调用统一TensorFlow会话session的代码:

import tensorflow as tf

import threading

def thread_function(sess, i):
inn = [1.3, 4.5]
A = tf.placeholder(dtype=float, shape=(None), name="input")
P = tf.Print(A, [A])
Q = tf.add(A, P)
sess.run(Q, feed_dict={A: inn})

def main(sess):

thread_list = []
for i in range(0, 4):
t = threading.Thread(target=thread_function, args=(sess, i))
thread_list.append(t)
t.start()

for t in thread_list:
t.join()

if __name__ == '__main__':

sess = tf.Session()
main(sess)

View Code

 

该代码很不幸,不能运行,报错:​​RuntimeError: The Session graph is empty. Add operations to the graph before calling run().​

tensorflow1.x——如何在python多线程中调用同一个session会话_Tensorflow

 

 

 

 

 

根据poster中回帖给出的解决方法可以知道,在主线程中Session启动后调用的计算图graph默认就是默认Graph,但是在子线程中则需要对使用的计算图进行指定,给出修改后的可运行的代码:

import tensorflow as tf
import threading

def thread_function(i):
with sess.graph.as_default():
inn = [1.3, 4.5]
A = tf.placeholder(dtype=float, shape=(None), name="input")
P = tf.Print(A, [A, "hello:"])
Q = tf.add(A, P)
# print(sess.run(Q, feed_dict={A: inn}))
sess.run(Q, feed_dict={A: inn})

def main(sess):
thread_list = []
for i in range(0, 4):
t = threading.Thread(target=thread_function, args=(i,))
thread_list.append(t)
t.start()

for t in thread_list:
t.join()

if __name__ == '__main__':
sess = tf.Session()
main(sess)

View Code

 

tensorflow1.x——如何在python多线程中调用同一个session会话_tensorflow_02

 

 

 

 

不过需要注意的是由于python中的GIL,因此python中线程是不能并发的,也就是说同一时刻多个线程中只能有一个线程在运行,因此即使多个python线程调用同一个session会话,其总的用时是单线程运行时间的累加,并不能起到加速的作用,为了更清晰的验证给出下面代码:

import tensorflow as tf
import numpy as np
import threading
import time

def thread_function(sess, Q, A, inn):
with sess.graph.as_default():
sess.run(Q, feed_dict={A: inn})

def main(sess):
A = tf.placeholder(dtype=float, shape=(500, 500), name="input")
Q = tf.Variable(tf.random_normal(shape=(500, 500)), dtype=float, name="input_variable")
Q = tf.add(A, Q)
for _ in range(10000):
Q += tf.matmul(A, Q)
# print(sess.run(Q, feed_dict={A: inn}))

inn = np.random.random(size=(500, 500))
thread_list = []
a_time = time.time()

sess.run(tf.global_variables_initializer())

print(a_time)
for i in range(0, 3):
t = threading.Thread(target=thread_function, args=(sess, Q, A, inn))
thread_list.append(t)
t.start()

for t in thread_list:
t.join()
b_time = time.time()
print(b_time)
print(b_time-a_time)

if __name__ == '__main__':
sess = tf.Session()
main(sess)

 

上面代码,在python中开三个线程调用相同的TensorFlow的Session会话,结果:

tensorflow1.x——如何在python多线程中调用同一个session会话_强化学习_03

 

 

 

 

改成两个线程:

tensorflow1.x——如何在python多线程中调用同一个session会话_python_04

 

 

 

 

 

改成一个线程:

tensorflow1.x——如何在python多线程中调用同一个session会话_python_05

 

 

 

 

可以看到虽然可以使用python多线程调用同一个TensorFlow的session会话,但是并不能对性能有什么提升,多线程运算其实也是串行的,或许只有少量提升,其主要原因就是python的多线程其实不能并发运行的。

 

 

 

===========================================

 

标签:__,sess,tensorflow1,thread,python,session,tf,多线程
From: https://blog.51cto.com/u_15642578/5857002

相关文章

  • C#多线程(一)线程基础篇
    C#多线程(一)线程基础篇 线程基础视频已经发布到B站参考文章:《ThreadinginC#》(JosephAlbahari)https://www.albahari.com/threading/《ThreadinginC#》中文翻......
  • 多线程下带事务的删除大量数据引起的锁等待超时
    @Override@Transactional(readOnly=false,propagation=Propagation.REQUIRES_NEW)//我建议不要用这个注解,他是声明式事务粒度过大,建议用使用编程式事务,可控性......
  • 异步和多线程有什么区别
    一、异步和多线程有什么区别?其实,异步是目的,而多线程是实现这个目的的方法。 多线程和异步操作两者都可以达到避免调用线程阻塞的目的,从而提高软件的可响应性。甚至......
  • C#多线程之高级篇(上)
    前言抛开死锁不谈,只聊性能问题,尽管锁总能粗暴的满足同步需求,但一旦存在竞争关系,意味着一定会有线程被阻塞,竞争越激烈,被阻塞的线程越多,上下文切换次数越多,调度成本越大,显然......
  • 多线程等待
    多线程等待温故而知新,好久没有用到,突然忘记 方法一CountDownEvent类usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usi......
  • 什么是Session;request.getSession().setAttribute()
    Session:会话控制,是服务器为了保存用户状态而创建的一个特殊的对象。=>用于存储信息的一个对象   当我们在服务端使用session时,首先要获取session,下面这个图就对服务......
  • python 多进程 多线程 协程
    多进程-进程池1fromconcurrent.futuresimportProcessPoolExecutor23withProcessPoolExecutor(max_workers=10)asexecutor:4results=executor.map......
  • 会话保持 Session和cookie
      Session是什么?      Session在网络中称为会话控制,是服务器为了保护用户状态而创建的一个特殊的对象,简而言之,session就是一个对象,用于存储信息。 Sess......
  • ActiveMQ经典的使用模式(利用多线程处理消费端)
    今天看视频,里面讲了一个经典的例子,是工作中很常用的,特此将这种模式记录下来.这个例子使用了ActiveMQ的选择器,也使用了之前学的自定义线程池.队列的使用,而且很好的利......
  • 响应式编程(反应式编程)的来龙去脉(同步编程、多线程编程、异步编程再到响应式编程)
    响应式编程的来龙去脉(同步编程、多线程编程、异步编程再到响应式编程)文章目录​​响应式编程的来龙去脉(同步编程、多线程编程、异步编程再到响应式编程)​​​​简介​​​​......