[英]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函數中調用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"
這是對管道或套接字的實現限制,已在問題8426中進行了很好的描述:multiprocessing.Queue無法獲取()非常大的對象 。 注意它也適用於很多小物體。
解
要么
Queue.cancel_join_thread()
文獻資料
請記住,將項目放入隊列的進程將在終止之前等待,直到所有緩沖的項目由“ feeder”線程饋送到基礎管道為止。 (子進程可以調用隊列的cancel_join_thread()方法來避免這種行為。)
這意味着,無論何時使用隊列,都需要確保在加入該流程之前,將最終刪除隊列中已放置的所有項目。 否則,您無法確定將項目放入隊列的進程將終止。 還請記住,非守護進程將自動加入。
— 多處理-編程指南
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.