我正在运行Python 2.7.2 (default, Jun 12 2011, 15:08:59) [MSC v.1500 32 bit (Intel)] on win32
。
我生成了4个进程,给它们2个队列 - 用于任务和结果,并在最后加入任务队列。当任务计数达到一定数量时 - 例如njobs = 10000
- 即使所有任务都已完成,一些子进程和主进程也不会退出。
为什么会这样?
用于说明此内容的代码
def worker(job_queue, result_queue):
import Queue
while True:
try:
j = job_queue.get(False)
except Queue.Empty:
exit('done')
else:
result_queue.put_nowait(j)
job_queue.task_done()
if __name__ == "__main__":
from multiprocessing import JoinableQueue, Process, cpu_count
job_queue = JoinableQueue()
result_queue = JoinableQueue()
njobs = 10000
for i in xrange(njobs):
job_queue.put(i)
cpus = cpu_count()
for i in xrange(cpus):
p = Process(target=worker, args=(job_queue, result_queue))
p.start()
job_queue.join()
print("DONE")
任务越长,某人(或所有)进程挂起所需的任务数就越少。最初,我正在与此进行序列匹配。当队列大约500时,它通常会留下3个进程。
答案 0 :(得分:1)
显然,队列中包含超过6570项可能会导致死锁(此thread中的更多信息)。你可以做的是在主要执行结束时清空result_queue
:
while not result_queue.empty():
result_queue.get(False)
result_queue.task_done()
print "Done"
请注意,您不必在辅助功能中调用exit
,return
就足够了:
except Queue.Empty:
print "done"
return
您也可以考虑使用Pool:
from multiprocessing import Pool
def task(arg):
"""Called by the workers"""
return arg
def callback(arg):
"""Called by the main process"""
pass
if __name__ == "__main__":
pool = Pool()
njobs = 10000
print "Enqueuing tasks"
for i in xrange(njobs):
pool.apply_async(task, (i,), callback=callback)
print "Closing the pool"
pool.close()
print "Joining the pool"
pool.join()
print "Done"
答案 1 :(得分:1)
这是Issue 8426: multiprocessing.Queue fails to get() very large objects中详细描述的管道或套接字的实现限制。请注意,它也适用于许多小物件。
<强>解决方案强>
无论
Queue.cancel_join_thread()
<强>文档强>
请记住,将项目放入队列的进程将等待 在终止之前,直到所有缓冲的项目都由 “馈线”螺纹到底层管道。 (子进程可以调用 队列的cancel_join_thread()方法可以避免这种行为。)
这意味着无论何时使用队列,您都需要确保这一点 所有已放入队列的项目最终都将被删除 在流程加入之前。否则你不能确定 将项目放入队列的进程将终止。记得 此外,非守护进程将自动加入。