Process.join()和队列不能处理大量数据

时间:2015-07-29 18:43:01

标签: python python-2.7 python-multiprocessing

我试图分开循环,即

N = 1000000
for i in xrange(N):
    #do something

使用multiprocessing.Process,它适用于N的小值。 当我使用更大的N值时出现问题。在p.join()之前或期间发生了一些奇怪的事情,并且程序没有响应。如果我把print i,而不是q.put(i)放在函数f的定义中,一切都运行良好。

我将不胜感激任何帮助。这是代码。

from multiprocessing import Process, Queue

def f(q,nMin, nMax): # function for multiprocessing
    for i in xrange(nMin,nMax):
        q.put(i)

if __name__ == '__main__':

    nEntries = 1000000

    nCpu = 10
    nEventsPerCpu = nEntries/nCpu
    processes = []

    q = Queue()

    for i in xrange(nCpu):
        processes.append( Process( target=f, args=(q,i*nEventsPerCpu,(i+1)*nEventsPerCpu) ) )

    for p in processes:
        p.start()

    for p in processes:
        p.join()

    print q.qsize()

1 个答案:

答案 0 :(得分:11)

您正在尝试不受限制地增加队列,并且您正在加入正在等待队列中的空间的子进程,因此您的主进程将停止等待该进程完成,并且它永远不会。

如果在加入之前将数据从队列中拉出来,它将正常工作。

您可以使用的一种技术是这样的:

while 1:
    running = any(p.is_alive() for p in processes)
    while not queue.empty():
       process_queue_data()
    if not running:
        break

根据文档,p.is_alive()应该执行隐式连接,但它似乎也暗示最佳实践可能是在此之后在所有线程上显式执行连接。

编辑:虽然这很清楚,但可能并非完全符合要求。如何使它更好地执行将是高度任务和机器特定的(一般来说,你不应该一次创建那么多进程,除非有些将在I / O上被阻止)。

除了将进程数量减少到CPU数量之外,还有一些简单的修复方法可以使它更快(再次,视具体情况而定)可能如下所示:

liveprocs = list(processes)
while liveprocs:
    try:
        while 1:
            process_queue_data(q.get(False))
    except Queue.Empty:
        pass

    time.sleep(0.5)    # Give tasks a chance to put more data in
    if not q.empty():
        continue
    liveprocs = [p for p in liveprocs if p.is_alive()]