Python:如何并行化具有许多函数输入的嵌套 for 循环中使用的函数?

Python: How to parallelize functions used in nested for loops with many function inputs?

我希望加快一个缓慢的 运行ning 循环,但不要认为我用最好的方法来解决这个问题。我想并行化一些代码,这些代码 运行 是我编写的一个函数,但在尝试弄清楚使用 python 的 multiprocessing 模块时如何准确地表达输入参数时遇到了一些麻烦.我的代码基本上是以下形式:

a = some_value
b = some_value
c = some_value
for i in range(1,101):
    for j in range(1,101):
        b = np.array([i*0.001,j*0.001]).reshape((2,1))
        (A,B,C,D) = function(a,b,c,d)

所以我的函数本身采用各种参数,但对于这个特定用途,我只需要改变一个变量(它是两个值的数组)并创建一个值网格。此外,所有其他输入都是整数。我熟悉通过以下示例代码使用工作池并行化此类循环的非常简单的示例:

pool = mp.Pool(processes=4)
input_parameters = *list of iterables for multiprocessing*
result = pool.map(paramest.parameter_estimate_ND, input_parameters)

其中可迭代列表是使用 itertools 模块创建的。因为我只更改函数的一个输入变量,而所有其他变量都已声明,所以我在构造此类输入参数时遇到麻烦。所以我真正想要的是同时使用 multiprocessing 到 运行 不同的输入来加速 for 循环的执行。

我的问题是,如何构建 multiprocessing 的使用来并行化函数上 运行 的代码,同时仅更改特定变量的输入?

我是否以最好的方式处理这个问题?有没有更好的方法来做这样的事情?

谢谢!

通常情况下,您只需要担心嵌套循环的内部循环的并行化。假设对 function 的每次调用都足够重,值得 运行ning 作为一项任务,一次将其中的 100 个放入池中应该绰绰有余。


那么,如何并行化该内部循环?

把它变成一个函数就可以了:

def wrapper(a, c, d, i, j):
    b = np.array([i*0.001,j*0.001]).reshape((2,1))
    return function(a,b,c,d)

现在:

for i in range(1,101):
    pfunc = partial(function, a, c, d, i)
    ABCDs = pool.map(pfunc, range(1, 101))

或者,您甚至可以只在 i 循环中定义包装函数,而不是创建部分函数:

for i in range(1,101):
    def wrapper(j):
        b = np.array([i*0.001,j*0.001]).reshape((2,1))
        return function(a,b,c,d)
    ABCDs = pool.map(wrapper, range(1, 101))

如果您 运行 在通过池的队列传递闭包变量时遇到问题,那很容易;你实际上不需要捕获变量,只需要捕获值,所以:

for i in range(1,101):
    def wrapper(j, *, a=a, c=c, d=d, i=i):
        b = np.array([i*0.001,j*0.001]).reshape((2,1))
        return function(a,b,c,d)
    ABCDs = pool.map(wrapper, range(1, 101))

如果事实证明单独使用 j 并行度不够,您可以轻松地将其更改为映射到 (i, j)

def wrapper(i, j, *, a=a, b=b, c=c, d=d):
    b = np.array([i*0.001,j*0.001]).reshape((2,1))
    return function(a,b,c,d)
for i in range(1,101):
    ABCDs = pool.map(wrapper, itertools.product(range(1, 101), range(1, 101)))

ABCDs 将成为 A, B, C, D 值的可迭代对象,因此很可能,无论您想用 A, B, C, D 做什么,都只是以下问题:

    for A, B, C, D in ABCDs:
        # whatever