簡體   English   中英

多處理池和隊列

[英]Multiprocessing pool and queues

我在池中使用多處理。 我需要將結構作為參數傳遞給必須在單獨的進程中使用的函數。 我遇到了與multiprocessing.Pool的映射功能有關的問題,因為我無法復制Pool.QueuePool.Array 該結構將在運行中用於記錄每個終止過程的結果。 這是我的代碼:

import multiprocessing
from multiprocessing import Process, Manager, Queue, Array
import itertools
import time

def do_work(number, out_queue=None):
    if out_queue is not None:
        print "Treated nb ", number
        out_queue.append("Treated nb " + str(number))
    return 0


def multi_run_wrapper(iter_values):
    return do_work(*iter_values)

def test_pool():
    # Get the max cpu
    nb_proc = multiprocessing.cpu_count()

    pool = multiprocessing.Pool(processes=nb_proc)
    total_tasks = 16
    tasks = range(total_tasks)

    out_queue= Queue()  # Use it instead of out_array and change out_queue.append() into out_queue.put() in the do_work() function.
    out_array = Array('i', total_tasks)
    iter_values = itertools.izip(tasks, itertools.repeat(out_array))
    results = pool.map_async(multi_run_wrapper, iter_values)

    pool.close()
    pool.join()
    print results._value
    while not out_queue.empty():
        print "queue: ", out_queue.get()
    print "out array: \n", out_array

if __name__ == "__main__":
    test_pool()

我需要在一個分離的進程中啟動一個worker,並將輸出隊列作為參數傳遞。 我還想指定包含有限數量的正在運行的進程的池。 為此,我正在使用pool.map_async()函數。 不幸的是,上面的代碼給了我一個錯誤:

Exception in thread Thread-2:
Traceback (most recent call last):
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 808, in __bootstrap_inner
    self.run()
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 761, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/pool.py", line 342, in _handle_tasks
    put(task)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/queues.py", line 77, in __getstate__
    assert_spawning(self)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/forking.py", line 52, in assert_spawning
    ' through inheritance' % type(self).__name__
RuntimeError: Queue objects should only be shared between processes through inheritance

我相信是因為正如我在文檔中所讀到的那樣, Queue永遠無法被復制。 然后我想到將隊列設為全局變量,這樣就不再需要傳遞它了,但是在我看來,這太混亂了。 我還想到了使用multiprocessing.Array代替

out_array = Array('i', total_tasks)

但是會出現與隊列相同的錯誤:

# ...
RuntimeError: SynchronizedArray objects should only be shared between processes through inheritance

我需要在相對較大的軟件中使用此功能-使用多處理程序並從子進程交換信息-所以我希望我的代碼保持整潔。

如何以一種優雅的方式將隊列傳遞給我的工人?

當然,歡迎使用任何其他處理主要規范的方法。

multiprocessing.Pool在其工作隊列中不會接受multiprocessing.Queue作為參數。 我相信這是因為它在內部使用隊列將數據來回發送到工作進程。 有幾種解決方法:

1)您真的需要使用隊列嗎? Pool函數的一個優點是它們的返回值被發送回主進程。 通常,遍歷池中的返回值比使用單獨的隊列要好。 通過檢查queue.empty()也可以避免引入競爭條件

2)如果必須使用Queue ,則可以使用multiprocessing.Manager一個。 這是共享隊列的代理,可以作為參數傳遞給Pool函數。

3)您可以在創建Pool時使用初始化程序將常規Queue傳遞給工作進程(例如https://stackoverflow.com/a/3843313 )。 這有點怪。

我上面提到的比賽條件來自:

while not out_queue.empty():
    print "queue: ", out_queue.get()

當工作進程填充隊列時,您可能會遇到以下情況:隊列當前為空,因為工作進程將要放入一些東西。 如果您此時檢查.empty() ,則將提早結束。 更好的方法是將標記值放入隊列中,以在完成將數據放入隊列時發出信號。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM