python - 使用带有关键字参数的 multiprocessing.Pool.map() 函数?

标签 python multiprocessing

我正在尝试将关键字参数传递给 Python 的 multiprocessing.Pool 实例中的 map 函数。

Using map() function with keyword arguments 推断, 我知道我可以使用 functools.partial() 如下:

from multiprocessing import Pool
from functools import partial
import sys

# Function to multiprocess
def func(a, b, c, d):
    print(a * (b + 2 * c - d))
    sys.stdout.flush()

if __name__ == '__main__':
    p = Pool(2)
    # Now, I try to call func(a, b, c, d) for 10 different a values,
    # but the same b, c, d values passed in as keyword arguments
    a_iter = range(10)
    kwargs = {'b': 1, 'c': 2, 'd': 3}

    mapfunc = partial(func, **kwargs)
    p.map(mapfunc, a_iter)

输出是正确的:

0
2
4
6
8
10
12
14
16
18

这是这样做的最佳实践(最“pythonic”方式)吗?我觉得:

1)Pool常用;

2) 常用关键字参数;

3) 但是像我上面的例子这样的组合用法有点像实现这个的“hacky”方式。

最佳答案

如果默认参数很大,使用 partial 可能不是最佳选择。传递给 map 的函数在发送给 worker 时会被重复 pickle(针对可迭代对象中的每个参数一次);全局 Python 函数(本质上)通过发送限定名称进行 pickle 编辑(因为在另一端定义了相同的函数而无需传输任何数据)而 partialpickle 编辑为函数的 pickle 和所有提供的参数。

如果 kwargs 都是小型原语,就像您的示例一样,这并不重要;发送额外参数的增量成本是微不足道的。但是如果 kwargs 很大,比如说,kwargs = {'b': [1] * 10000, 'c': [2] * 20000, 'd': [3]*30000 ,这是一个令人讨厌的代价。

在这种情况下,您有一些选择:

  1. 在全局级别滚动您自己的函数,其工作方式类似于 partial,但 pickle 不同:

    class func_a_only(a):
        return func(a, 1, 2, 3)
    
  2. initializer 参数用于 Pool,这样每个工作进程都会设置一次状态,而不是每个任务一次,这样您就可以确保数据可用,即使你在基于 spawn 的环境中工作(例如 Windows)

  3. 使用Manager在所有进程之间共享一个数据副本

可能还有一些其他方法。重点是,partial 适用于不会产生巨大 pickle 的参数,但如果绑定(bind)参数很大,它可能会杀了你。

注意:在这种特殊情况下,如果您使用的是 Python 3.3+,您实际上并不需要 partial,并且避免使用 dict 支持 tuple 可以节省少量开销。在不添加任何新功能的情况下,只需一些导入,您就可以替换:

kwargs = {'b': 1, 'c': 2, 'd': 3}
mapfunc = partial(func, **kwargs)
p.map(mapfunc, a_iter)

与:

from itertools import repeat

p.starmap(func, zip(a_iter, repeat(1), repeat(2), repeat(3)))

达到类似的效果。需要明确的是,这种“修复”的 partial 没有任何问题(两种方法在处理大型对象时都会遇到相同的问题),这只是一种偶尔有用的替代方法。

关于python - 使用带有关键字参数的 multiprocessing.Pool.map() 函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35761325/

相关文章:

python - 为什么我不能在 OSX 上的 pipenv 中安装 m2crypto?

python - 如何在展平 MultiIndex 列并将样式应用于 DataFrame 后删除索引列?

Python 和多处理示例

r - 多处理两个数据帧之间的行匹配操作的最佳方式

Python多处理内存增加

python - 大容量插入错误代码 3 : The system cannot find the path specified

java - Java(以及 Python)中字典的最佳数据结构

python - IPython 在 Django shell 中不起作用

python - 搁置只读多处理不安全吗?

线程之间的Python共享类实例