使用scipy.integrate.quad并行计算矩阵元素

时间:2019-10-08 12:16:21

标签: python parallel-processing scipy multiprocessing quad

我必须使用具有数值积分(scipy.integrate.quad)的函数来评估矩阵的每个元素。矩阵的元素是5202x3465灰度图像的像素。
我可以使用GPU,并且希望并行评估尽可能多的元素,因为现在,使用线性编程,整个计算需要24个小时以上。
这是示例代码:

for i in range(0, rows):
    for j in range(0, columns):
        img[i, j] = myFun(constant_args, i, j)

def myFunc(constant_args, i, j):
    new_pixel = quad(integrand, constant_args, i, j)
    ... other calculations ... 
    return new_pixel

我试图像这样使用多重处理(如mp):

arows = list(range(0, rows))
acolumns = list(range(0, columns))
with mp.Pool() as pool:
    img = pool.map(myFunc, (constant_args, arows, acolumns))

或带有img = pool.map(myFunc(constant_args),(箭头,列))
却给了我
TypeError:myFunc()缺少2个必需的位置参数:“ j”和“ i”

我不理解其他示例中的工作原理,也不知道文档中使用的术语。
如果有人建议采用其他方法,我只想将嵌套循环划分为子线程。
ps。我尝试使用numba,但在与某些Scipy库进行交互时却给出了错误

提前感谢您的帮助!

2 个答案:

答案 0 :(得分:0)

首先,错误在于您对public TR MeasureExecutionTime<T1, T2, T3, T4, T5, T6, TR>(this Func<T1, T2, T3, T4, T5, T6, TR> func, out long executionTime) { Stopwatch stopwatch = Stopwatch.StartNew(); TR tr = func(); stopwatch.Stop(); executionTime = stopwatch.ElapsedMilliseconds; return tr; } ... var result = MeasureExecutionTime(() => obj.Process(p1, p2, p3, p4, p5, p6), out long executionTime); -操作的调用。必须是:

map

但是,这可能不会导致您要查找的内容,因为它仅通过3个参数(必须为列表)运行。它不是通过它们的组合来运行的,尤其是arows = list(range(0, rows)) acolumns = list(range(0, columns)) with mp.Pool() as pool: img = pool.map(myFunc, constant_args, arows, acolumns) arows。例如,如果acolumns具有3个元素,则constant_args将在3次迭代后停止,而不会遍历较长的列表Pool.maparows

首先,您应该对行索引和列索引进行所有组合

acolumns

这会导致类似(所有可能的组合)

from itertools import product, repeat
comb = list(product(arows, acolumns))

接下来,我将这些组合与您的[(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)]

constant_args

它产生一个元组列表,每个元组包含两个元素。第一个是您的像素位置,第二个是您的constant_args = [10, 11] arguments = list(zip(comb , repeat(constant_args)))

constant_args

现在,我们必须对您的[((1, 1), [10, 11]), ((1, 2), [10, 11]), ((1, 3), [10, 11]), ((2, 1), [10, 11]), ((2, 2), [10, 11]), ((2, 3), [10, 11]), ((3, 1), [10, 11]), ((3, 2), [10, 11]), ((3, 3), [10, 11])] 进行一些修改:

myFunc

最后,我们使用Pool.starmap发挥作用(参见此处:starmap usage):

def myFunc(pix_id, constant_args):
    new_pixel = quad(integrand, constant_args, pix_id[0], pix_id[1])
    ... other calculations ... 
    return new_pixel

发生的情况是,with mp.Pool() as pool: img = pool.starmap(myFunc, arguments ) 接受一个元组列表,并将其提供为函数的输入。但是,starmap会自动将元组列表解压缩为单个参数以供您使用。第一个参数是由两个元素组成的starmap,第二个参数是pix_id

答案 1 :(得分:0)

您可以使用quadpy(我的项目之一)。它会执行 vectorized 计算,因此运行速度非常快。 输出形状为2x2的示例:

import quadpy


def f(x):
    return [[x ** 2, x**3], [x**4, x**5]]


scheme = quadpy.line_segment.gauss_legendre(5)
val = scheme.integrate(f, [0, 1])
print(val)
[[0.33333333 0.25      ]
 [0.2        0.16666667]]

f的输出必须为(..., x.shape)形状,并且...可以是任何元组,例如(5202, 3465)