【问题标题】:Tensorflow classification not running correctly with multiprocessing, but is with multithreadingTensorflow 分类无法在多处理中正确运行,但在多线程中
【发布时间】:2017-03-30 17:55:03
【问题描述】:

我有一个应用程序,它应该每 5 秒对图像进行一次并行分类。我想绕过全局解释器锁,所以我尝试使用多处理库而不是多线程。或多或少,我的代码如下所示:

# Loads label file, strips off carriage return
label_lines = [line.rstrip() for line 
                   in tf.gfile.GFile("/home/aneksteind/tensorflowSource/output_labels.txt")]

# Unpersists graph from file
f = tf.gfile.FastGFile("/home/aneksteind/tensorflowSource/output_graph.pb", 'rb')
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
_ = tf.import_graph_def(graph_def, name='')

sess = tf.Session()
mainGraph = sess.graph

# a function that starts a thread for each region of interest to classify
def checkFrames():
    timer = threading.Timer(5.0, checkFrames)
    timer.daemon = True
    timer.start()
    if(started):
        index = 0
        threads = []
        for roi in rois:
            p = Process(target=containsPlane, args=(frame, roi, index))
            p.daemon = True
            p.start()
            index += 1

def containsPlane(frame, roi, index):
    tempGraph = mainGraph
    tempSession = tf.Session(graph=tempGraph)
    tempTensor = tempSession.graph.get_tensor_by_name('final_result:0')
    predictions = tempSession.run(tempTensor, \
             {'DecodeJpeg:0': subframe})

    ...

当我使用线程运行此代码时,它运行得很好。它在第一次分类之前打印出每个初步消息/警告,并且只对每个图像进行分类,但不是并行的。

当我更改为进程时,初步消息/警告会反复出现,并且图像永远不会分类。这可能是由于会话共享某种状态吗?我可以做些什么不同的事情来并行分类多个图像?

【问题讨论】:

  • 您不能将global vars 与processes 一起使用。 Vars 必须在 process 内,否则您必须使用 shared memory
  • @stovfl 我怎么知道哪个变量是需要成为 multiprocess.Value 的变量?
  • 因为 TensorFlow 内部使用 pthreads 我不认为它会与 python 处理包兼容(在存在分叉的情况下线程代码的行为很难调试和理解)。
  • @AlexandrePassos 有没有办法使用 tensorflow 并行运行作业(每个作业都必须运行会话)?
  • 如果您启动许多 python 进程并使用相同的集群规范将它们连接到同一设备,它们将共享状态。否则你可以使用 C++ 线程来调用 session.run。

标签: python multithreading python-3.x parallel-processing tensorflow


【解决方案1】:

来自 TensorFlow 文档:创建一个新的 TensorFlow 会话。
如果在构建会话时没有指定图表参数,则默认图表将在会话中启动。如果您使用多个图(在同一进程中使用 tf.Graph() 创建,则必须为每个图使用不同的会话,但每个图可以在多个会话中使用。在这种情况下,通常会更清晰将要显式启动的图形传递给会话构造函数。

我认为您应该将graph=tf.Graph() 作为parameter 提供给def containsPlane(...)。尝试独立于global vars 并尝试在def containsPlane(...) 中创建session


你有三个参数args=(frame, roi, index),但我没有看到在def containsPlane(..) 中使用它们?


问题:...使用线程运行此代码,它运行得很好。 ...,但不是并行的。
for roi in rois: threads.append(threading.Thread(...

你启动roiThreads,所以我无法想象为什么执行不是并行

您尝试以这种方式使用multiprocessing 将失败,因为您应该启动更多 processes,因为您的机器有内核。 启动更多将导致交换,从而降低整体性能。

问题:我如何判断哪个变量需要成为 multiprocess.Value?

所有只读


不明白您为什么要这样做:

sess = tf.Session()
mainGraph = sess.graph
# ...
def containsPlane(frame, roi, index):
    tempGraph = mainGraph
    tempSession = tf.Session(graph=tempGraph)  

为什么不简单:

def containsPlane(frame, roi, index):
    tempSession = tf.Session()  

【讨论】:

  • 线程由于全局解释器锁而不再并行运行。至于其他问题,我没有您提供的简单示例,因为当我尝试找不到张量流图时,我不想为我想要分类的每个 roi(感兴趣区域)加载它。该帧是我正在从中获取感兴趣区域的当前帧
  • @DavidAnekstein:更新了我的答案
猜你喜欢
  • 1970-01-01
  • 2018-12-19
  • 1970-01-01
  • 2013-01-24
  • 2016-03-21
  • 2016-01-04
  • 2017-02-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多