簡體   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