繁体   English   中英

作业计数超过n时,进程无法退出()

[英]Processes fail to exit() when job count exceeds n

Python 2.7.2 (default, Jun 12 2011, 15:08:59) [MSC v.1500 32 bit (Intel)] on win32运行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个进程挂起。

显然,队列中有6570个以上的项目可能会导致死锁(此线程中的更多信息)。 您可以做的是在主执行结束时输入空result_queue

while not result_queue.empty():
    result_queue.get(False)
    result_queue.task_done()
print "Done"

请注意,您不必在worker函数中调用exitreturn就足够了:

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"

这是对管道或套接字的实现限制,已在问题8426中进行了很好的描述:multiprocessing.Queue无法获取()非常大的对象 注意它也适用于很多小物体。

要么

  • 确保足够快地同时使用结果队列
  • 从子进程中,调用Queue.cancel_join_thread()

文献资料

请记住,将项目放入队列的进程将在终止之前等待,直到所有缓冲的项目由“ feeder”线程馈送到基础管道为止。 (子进程可以调用队列的cancel_join_thread()方法来避免这种行为。)

这意味着,无论何时使用队列,都需要确保在加入该流程之前,将最终删除队列中已放置的所有项目。 否则,您无法确定将项目放入队列的进程将终止。 还请记住,非守护进程将自动加入。

多处理-编程指南

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM