为什么即使完成对池的映射调用,进程也需要很长时间才能加入?

时间:2016-08-29 11:28:51

标签: python parallel-processing multiprocessing zombie-process

这是关于multiprocessing 5中Python 3.模块的另一个问题。我的问题是我知道所有分叉处理完成了他们的工作(我可以在Queue看到他们的结果),AsyncResult.result()返回True,这意味着作业已完成,但是当我继续使用PoolObj.join时(),它需要永远。我知道我可以使用PoolObj.terminate()并继续我的生活,但我想知道为什么会发生这种情况?

我使用以下代码:

def worker(d):
    queue.put(d)

def gen_data():
    for i in range(int(1e6)):
        yield i

if __name__ == "__main__":
    queue = Queue(maxsize=-1)
    pool = Pool(processes=12)
    pool_obj_worker = pool.map_async(worker, gen_data(), chunksize=1)
    pool.close()

    print ('Lets run the workers...\n')
    while True:
        if pool_obj_worker.ready():
            if pool_obj_worker.successful():
                print ('\nAll processed successfully!') # I can see this quickly, so my jobs are done
            else:
                print ('\nAll processed. Errors encountered!')
            sys.stdout.flush()
            print (q.qsize()) # The size is right that means all workers have done their job
            pool.join() # will get stuck here for long long time
            queue.put('*')           
            break
    print ('%d still to be processed' %
           pool_obj_worker._number_left)
    sys.stdout.flush()
    time.sleep(0.5)

我做错了吗?请赐教。或者持有join()的进程是否已经僵尸?

1 个答案:

答案 0 :(得分:2)

这里的问题是你在工作中使用了额外的Queue,而不是Pool所使用的那个。{1}}。 当进程完成他们的工作时,他们都将加入FeederThread中使用的multiprocessing.Queue并且这些调用将挂起(可能是因为所有线程同时调用join并且可能会有一些奇怪的种族条件,调查并不容易。)

添加multiprocessing.util.log_to_stderr(10)允许在加入队列馈线线程时显示您的进程挂起。

要解决您的问题,您可以使用multiprocessing.SimpleQueue代替multiprocessing.Queue(因为没有支线线程而没有挂起,或者尝试使用提供相同功能的方法pool.unordered_imap你似乎实现的行为(给一个包含worker返回的结果的无序生成器)。