多处理具有多个输入的函数
Posted
技术标签:
【中文标题】多处理具有多个输入的函数【英文标题】:Multiprocessing a function with several inputs 【发布时间】:2011-05-26 16:25:10 【问题描述】:在 Python 中,multiprocessing
模块可用于在一系列值上并行运行函数。例如,这会生成 f 的前 100000 次评估的列表。
def f(i):
return i * i
def main():
import multiprocessing
pool = multiprocessing.Pool(2)
ans = pool.map(f, range(100000))
return ans
当 f 接受多个输入但只有一个变量变化时,是否可以做类似的事情?例如,您将如何并行化:
def f(i, n):
return i * i + 2*n
def main():
ans = []
for i in range(100000):
ans.append(f(i, 20))
return ans
【问题讨论】:
【参考方案1】:你可以使用穷人的柯里化(又名 wrap it):
new_f = lambda x: f(x, 20)
然后拨打new_f(i)
。
【讨论】:
Thils 将不与多处理的地图一起工作,因为它不支持不可“导入”的函数(使用 pickle 工具)【参考方案2】:有几种方法可以做到这一点。在问题中给出的示例中,您可以只定义一个包装函数
def g(i):
return f(i, 20)
并将这个包装器传递给map()
。更通用的方法是有一个包装器,它接受单个元组参数并将元组解包为多个参数
def g(tup):
return f(*tup)
或使用等效的 lambda 表达式:lambda tup: f(*tup)
。
【讨论】:
【参考方案3】:您可以使用functools.partial()
def f(i, n):
return i * i + 2*n
def main():
import multiprocessing
pool = multiprocessing.Pool(2)
ans = pool.map(functools.partial(f, n=20), range(100000))
return ans
【讨论】:
我知道这是允许的,但是为什么只有在模块顶层定义的函数可以被腌制? 你能澄清一下关于使用部分的时刻吗 - 看起来它忽略了参数的键:如果我想 pool.map 在第二个参数上 -partial(f, i=20)
- 我收到错误:参数有多个值 @987654326 @.
@Mikhail_Sam docs.python.org/2/library/functools.html#functools.partial 您要添加到部分的函数需要将第一个参数作为位置参数(例如运行 for 循环时的 'i'),其余的关键字参数应该在之后. 'i' 的所有值都作为列表/范围添加为 'pool.map' 函数的第二个参数。在您的示例中,当“i”的值已经可用作“池”函数的第二个参数时,您在部分函数中提供了一个值“i”,导致您出现自我解释错误/【参考方案4】:
如果您使用我的 multiprocessing
分支,称为 pathos
,您可以获得带有多个参数的池......并且还带有 lambda
函数。它的好处是您不必更改编程结构以适应并行工作。
>>> def f(i, n):
... return i * i + 2*n
...
>>> from itertools import repeat
>>> N = 10000
>>>
>>> from pathos.pools import ProcessPool as Pool
>>> pool = Pool()
>>>
>>> ans = pool.map(f, xrange(1000), repeat(20))
>>> ans[:10]
[40, 41, 44, 49, 56, 65, 76, 89, 104, 121]
>>>
>>> # this also works
>>> ans = pool.map(lambda x: f(x, 20), xrange(1000))
>>> ans[:10]
[40, 41, 44, 49, 56, 65, 76, 89, 104, 121]
【讨论】:
刚刚安装了 pathos - 能够更好地使用带有闭包等的本地函数,而无需任何全局部分或包装函数或其他任何东西。谢谢你。 @AlexL:请注意,如果您想要与multiprocessing
完全相同的接口但具有更好的序列化,您可以交替使用multiprocess
(pathos
将其安装为依赖项)。【参考方案5】:
这种技术被称为柯里化:https://en.wikipedia.org/wiki/Currying
不使用functools.partial
的另一种方法是在pool.map
中使用经典的map
命令:
def f(args):
x, fixed = args
# FUNCTIONALITY HERE
pool = multiprocessing.Pool(multiprocessing.cpu_count() - 1)
pool.map(f, map(lambda x: (x, fixed), arguments))
【讨论】:
以上是关于多处理具有多个输入的函数的主要内容,如果未能解决你的问题,请参考以下文章