簡體   English   中英

以字典為參數的 Python 多處理問題

[英]Python multiprocessing problem with dictionary as argument

我有一個函數通過多處理池並行化另一個函數,該池將字典作為輸入。 我希望下面的代碼只打印從 0 到 32 的數字。但是,結果顯示有很多數字被打印了不止一次。

有人有想法嗎?

import multiprocessing as mp
import numpy as np
import functools

def test(name, t_dict):
    t_dict['a'] = name
    return t_dict

def mp_func(func, iterator ,**kwargs):
    f_args = functools.partial(func, **kwargs)
    pool = mp.Pool(mp.cpu_count())
    res = pool.map(f_args, iterator)
    pool.close()
    return res


mod =dict()

m =33
res = mp_func(func=test, iterator=np.arange(m), t_dict=mod)
for di in res:
    print(di['a'])

問題是t_dict作為偏函數f_args的一部分f_args 偏函數是<class 'functools.partial'>實例。 創建部分時,它會獲得對test的引用和mod的空字典。 每次調用f_args ,都會修改部分對象上的那個字典。 在單個過程中使用列表更容易發現這一點。

>>> def foo(name, t_list):
...     t_list.append(name)
...     return t_list
... 
>>> mod = []
>>> f = functools.partial(foo, t_list=mod)
>>> f(0)
[0]
>>> f(1)
[0, 1]
>>> f(2)
[0, 1, 2]
>>> mod
[0, 1, 2]

當您pool.map(f_args, iterator)f_args被腌制並發送到每個子f_args成為工作人員。 因此,每個子進程都有一個唯一的字典副本,該副本將針對子進程碰巧獲得的每個迭代值進行更新。

為了效率,多處理將分塊數據。 也就是說,每個子進程都收到一個迭代值列表,它將處理成一個響應列表,以作為一個組返回。 但是由於每個響應都引用相同的單個 dict,當塊返回給父級時,所有響應都只保存最終值集。 如果處理了0, 1, 2 ,則返回2, 2, 2

解決方案將取決於您的數據。 在池進程和父進程之間來回傳遞數據的成本很高,因此理想情況下,數據完全在工作進程中生成。 在這種情況下,放棄partial並讓工作人員創建字典。

很可能你的情況比這更復雜。

import multiprocessing as mp
import numpy as np

def test(name):
    retrurn ('a':name}

def mp_func(func, iterator ,**kwargs):
    pool = mp.Pool(mp.cpu_count())
    res = pool.map(test, iterator)
    pool.close()
    return res

m =33
res = mp_func(func=test, iterator=np.arange(m))
for di in res:
    print(di['a'])

正如每個人都告訴您的那樣,一般來說,讓多個線程/進程都修改同一個位置,然后期望該位置具有您的線程賦予它的值是一個壞主意。

如果共享數據結構的所有變異只發生在一處,您的代碼將運行得更好。 所以總體方案是:

def worker(key):
    ... calculate value produced by key ...
    return key, value

def runner():
    with mp.Pool() as pool:
       for key, value in pool.imap_unordered(worker, np.arange(m), chunksize=...):
           ... do fast mutation here ...

暫無
暫無

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

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