我希望加快缓慢运行的循环,但不要认为我正在用最好的方法解决这个问题。我想并行化一些运行我编写的函数的代码,并且在尝试弄清楚使用 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
都足够重,值得作为任务运行,那么一次将 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