后台工作:使用单个后台线程或每个循环启动一个线程?

时间:2015-02-15 17:56:07

标签: python multithreading

我在python中进行了一些视频分析,我想使用多线程来加速我的分析。 没有多线程,我的程序可以用以下方式编写

for frame in video:
    res1 = run_costly_function1(frame, res_prev)
    res2 = run_costly_function2(frame, res_prev)
    res_prev = run_function2(res1, res2)

但是,函数run_costly_function1run_costly_function2不相互依赖,因此可以并行运行。我也大量使用OpenCV函数,它释放了全局解释器锁,因此我认为多线程应该是可行的。

我可以想出两种不同的解决方法:

  1. 每次迭代启动一个新线程,其任务是计算run_costly_function2

    for frame in video:
        background_worker = Thread(target=run_costly_function2, args=(frame, res_rev))
        background_worker.start()
        res1 = run_costly_function1(frame, res_rev)
        res2 = background_worker.join()
        res_prev = run_function2(res1, res2)
    
  2. 拥有一个后台线程并使用队列与之通信:

    q = queue.Queue()
    background_worker = Thread(target=background_worker_func, args=(q,))
    background_worker.start()
    
    for frame in video:
        q.put((frame, res_prev))
        res1 = run_costly_function1(frame, res_prev)            
        res2 = q.get()
        res_prev = run_function2(res1, res2)
    
  3. 我的问题是哪种方法更好?也许甚至有一个我忽略的第三种选择?如果它们有用,我愿意使用futures之类的其他模块。

    该解决方案应该扩展到每秒处理~100帧,我担心每秒创建100个线程(在方法1中)是昂贵的。但是,使用队列进行通信(在方法2中)实现起来似乎更复杂,因此更容易出错。

1 个答案:

答案 0 :(得分:0)

使线程操作繁重,因此创建与您拥有的核心一样多的线程并且可以有效地利用它。我认为在你的情况下,不改变算法,最大线程数是3。

为降低转换成本,请勿将轻型操作移至单独的线程。 使用适合特定情况的最快同步素数。 Somtimes beter解决方案不是挂起线程并等待循环。

队列适用于处理一串独立数据,以防独立数据工作可以轻松地与多个工作人员分开。处理结果后可以传递给下一个队列,依此类推。