为什么多处理中的get()需要花费很多时间在Python中?

时间:2018-04-27 02:54:34

标签: python multithreading face-recognition

我正在尝试在Python中使用多处理来在Raspberry Pi上进行人脸识别。为了充分利用所有4个核心,我使用了多线程概念。下面是我的(伪)代码的一部分:

count = 1

while True:

    image = cap.read

    if count == 1:
        r1 = pool.apply_async(func, [image]) # this is the image process module
        output = r2.get()  # this is used to get the results from processor #2
        showimage(output)  # show the processed results
    elif count == 2:
        r2 = pool.apply_async(func, [image]) # this is the image process module
        output = r3.get()  # this is used to get the results from processor #3
        showimage(output)  # show the processed results
    elif count == 3:
        r3 = pool.apply_async(func, [image]) # this is the image process module
        output = r4.get()  # this is used to get the results from processor #4
        showimage(output)  # show the processed results
    elif count == 4:
        r4 = pool.apply_async(func, [image]) # this is the image process module
        output = r1.get()  # this is used to get the results from processor #1
        showimage(output)  # show the processed results
        count = 0
        count += 1

据我所知,与实际图像捕捉(三个周期)相比,显示图像会有一些延迟。我对运行算法的理解是,存在一定程度的卡住现象。它可能如下所示:

  1. 顺利显示r1,r2,r3,r4的结果,然后卡住1秒,然后顺利显示r1-r4的结果......
  2. OR

    1. 顺利显示r2,r3,r4,r1的结果,然后卡住1秒,然后顺利显示r2-r1的结果......
    2. 它可以是从r1,r2,r3,r4开始的任何序列。我不明白是什么导致了这个卡住的事情?有人可以帮忙分析一下吗?感谢。

      以下是概况分析的快照:

      enter image description here

2 个答案:

答案 0 :(得分:1)

这是一个简单的例子,解释了你所看到的模式

假设你有4个人,前面有4个空杯水。把get()想象成“在你的杯子里喝完水,我要等到你继续前进”。将apply_async视为“我要填满你的杯子,开始喝酒,但我还在继续”。

那会发生什么:

count == 1
We fill person A's glass and they're drinking slowly
We wait for person B to finish their cup, it's already empty, we move on

count == 2
We fill person B's glass and they're drinking slowly
We wait for person C to finish their cup, it's already empty, we move on
...

count == 4
We fill person D's glass and they're drinking slowly
We wait for person A to finish their cup

好的,假设A需要30秒才能完成他们的水,但只花了5秒钟来完成上述步骤。

我们现在要等待25秒让A完成他们的饮料才能继续前行。但是在所有等待时间之后,B,C和D人也完成了他们的饮料,所以一旦A完成,我们将放大接下来的3个人,直到我们再次回到A。

答案 1 :(得分:0)

如果您确实希望尽快启动作业,并在结果可用时立即获取结果,而不阻止新作业被触发,则必须停止交错。

执行此操作的最简单方法(假设您希望按任务创建的顺序 1 )可能要等待后台线程,如下所示:

q = queue.Queue()

def handle():
    while True:
        res = q.get()
        output = res.get()
        showimage(output)

threading.Thread(target=handle)

while True:
    image = cap.read
    res = pool.apply_async(func, [image])
    q.put(res)

这个确切的设计可能不起作用 - 例如,如果必须在主线程上运行showimage,则必须交换两个线程,如果cap.read 必须运行你需要管理多个队列的主线程并使一切变得更复杂 - 但它应该表明这个想法。

<子> 1。如果您希望结果按照他们完成的任何顺序进行,那么从multiprocessing.Pool切换到concurrent.futures.ProcessPoolExecutor可能会更简单,因为等待future组比在AsyncResult组更容易一组spring-cloud-spring-service-connector个。但还有其他选择。