繁体   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