[英]Multiprocessing pool and queues
我在池中使用多處理。 我需要將結構作為參數傳遞給必須在單獨的進程中使用的函數。 我遇到了與multiprocessing.Pool
的映射功能有關的問題,因為我無法復制Pool.Queue
和Pool.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.