Python 为什么即使对池的映射调用完成,进程也要花费很长时间才能加入?
这是关于Python 为什么即使对池的映射调用完成,进程也要花费很长时间才能加入?,python,parallel-processing,multiprocessing,zombie-process,Python,Parallel Processing,Multiprocessing,Zombie Process,这是关于python3.5中的多处理模块的另一个问题。我的问题是,我知道所有的forked processed都完成了它们的工作(我可以在队列中看到它们的结果),AsyncResult.result()返回True,这意味着作业已经完成,但当我继续使用PoolObj.join()时,它将花费永远的时间。我知道我可以用PoolObj.terminate()继续我的生活,但我想知道为什么会发生这种情况 我正在使用以下代码: def worker(d): queue.put(d) def g
python3.
5中的多处理
模块的另一个问题。我的问题是,我知道所有的forked processed都完成了它们的工作(我可以在队列中看到它们的结果),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()
的进程已经僵化了吗?这里的问题是,您在工作进程中使用了一个额外的队列,而不是由池完成的队列。
当进程完成其工作时,它们都将加入多处理.Queue
中使用的FeederThread
,这些调用将挂起(可能是因为所有线程同时调用join
,并且可能存在一些奇怪的争用条件,不容易调查)
将multiprocessing.util.log\u添加到\u stderr(10)
中,可以显示您的进程在加入队列联接线程时挂起
要解决您的问题,您可以使用多处理.SimpleQueue
而不是多处理.Queue
(没有挂接连接,因为没有联接线程),或者尝试使用方法pool.unordered_imap
,该方法提供与您似乎实现的行为相同的行为(返回包含worker返回的结果的无序生成器).如果您减少要放入队列的内容的大小,会发生什么情况?问题甚至存在于较小的值1e5和1e4。但是,对于小于这些值的值,问题并不明显。将其减少到10
并尝试-它至少完成了还是仍然挂起?这可能与此有关,我也有类似的问题lem但是使用进程
。虽然在您的情况下,您说队列大小正确,因此可能会发生其他事情,但这可能会使您朝着正确的方向前进。另外,如果没有,会发生什么事。join()
有吗?即使有10个,也要加入暂停10秒。我正在使用12个进程,即使从pool\u obj\u worker.successful()收到True
后,也可以在进程监视器中看到它们
如果我使用collections.deque
代替多处理.Queue
,问题会得到解决,但没有用,因为我无法返回结果。我想每个fork都会初始化一个新的deque实例。谢谢Thomas。你说得对!加入队列会带来巨大的开销。如果使用pool,我如何监控作业的进度.imap_无序?这里还有一个相关问题!为什么imap生成器上的迭代会随着时间的推移而变慢。这是由于在列表中累积结果的影响吗?如果是这样,我如何解决这个问题?要监视进度,可以尝试访问IMAPUNORDEDITOR。_index
我看不到此处提供的代码有任何减速。Each当您访问生成器的某个元素时,它将从列表中删除,因此如果它处于平衡状态,则不会真正减速。可能您的对象比int
大,并且生成器会变大。这取决于您的使用情况。。