27

在 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
4

5 回答 5

42

您可以使用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
于 2010-12-16T17:26:42.807 回答
14

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

def g(i):
    return f(i, 20)

并将这个包装器传递给map(). 更通用的方法是有一个包装器,它接受单个元组参数并将元组解包为多个参数

def g(tup):
    return f(*tup)

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

于 2010-12-16T16:59:27.873 回答
8

如果您使用我的 fork of multiprocessing, called 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]
于 2015-08-14T00:41:29.917 回答
3

这种技术被称为柯里化:https ://en.wikipedia.org/wiki/Currying

另一种不使用内部functools.partial经典map命令的方法pool.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))
于 2018-11-08T08:47:47.020 回答
-3

你可以使用穷人的咖喱(又名包装它):

new_f = lambda x: f(x, 20)

然后打电话new_f(i)

于 2010-12-16T16:58:06.267 回答