Python多处理具有多个输入的函数

Mar*_*ell 17 python multiprocessing

在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
Run Code Online (Sandbox Code Playgroud)

当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
Run Code Online (Sandbox Code Playgroud)

mou*_*uad 30

你可以使用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
Run Code Online (Sandbox Code Playgroud)

  • 我知道这是允许的,但是为什么只对在模块顶层定义的函数进行腌制呢? (2认同)
  • @Mikhail_Sam https://docs.python.org/2/library/functools.html#functools.partial 您要添加到部分的函数需要将第一个参数作为位置参数(例如运行 for 循环时的“i”) ) 其余的关键字参数应位于其后。“i”的所有值都作为列表/范围添加为“pool.map”函数的第二个参数。在您的示例中,当“i”的值已经可用作“pool”函数的第二个参数时,您在部分函数中提供了“i”的值,导致您出现不言自明的错误/ (2认同)

Sve*_*ach 15

有几种方法可以做到这一点.在问题中给出的示例中,您可以定义包装函数

def g(i):
    return f(i, 20)
Run Code Online (Sandbox Code Playgroud)

并将此包装传递给map().更通用的方法是使用包含单个元组参数的包装器并将元组解包为多个参数

def g(tup):
    return f(*tup)
Run Code Online (Sandbox Code Playgroud)

或使用等效的lambda表达式:lambda tup: f(*tup).


Mik*_*rns 7

如果你使用我的fork 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]
Run Code Online (Sandbox Code Playgroud)