【问题标题】:Numpy piecewise function is slow in scipy quadNumpy分段函数在scipy quad中很慢
【发布时间】:2018-05-01 09:39:24
【问题描述】:

我试图以 numpy 方式和基本 pythonic 方式测量评估数学函数所花费的时间。首先,我测量了评估函数所需的时间。

import numpy as np
import scipy as sp
import scipy.integrate as si



def func1(x):
    return np.piecewise(x, [x<=2, x>2],
                    [lambda x: 2*x + pow(2, x),
              lambda x: -(pow(x, 2) + 2)]
                       )
def func2(x):
    if (x<=2): return 2*x + pow(2,x)
    else: return -(pow(x, 2) + 2)

data = np.linspace(-10, 10, 1000)
%timeit data1 = func1(data)
data2 = []
%timeit for i in range(0, np.size(data)): data2.append(func2(data[i]))

其实上面的结果和我预想的一样,numpy方式比基本方式快很多。

35.2 µs ± 110 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
771 µs ± 10.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

但是,在 scipy.integrate.quad 中发生了奇怪的事情。以基本的pythonic方式集成速度要快得多。为什么会这样?

%timeit si.quad(func1, -10, 10)
%timeit si.quad(func2, -10, 10)

5.59 ms ± 25.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
187 µs ± 39.3 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

【问题讨论】:

标签: python numpy scipy


【解决方案1】:

np.piecewise 仅在利用矢量化时才快速。当输入是标量时,它比等效的 python 慢得多,可能是由于开销:

from timeit import timeit
kwds = dict(globals=globals(), number=1000)

print(timeit("data1 = func1(data)", **kwds))
data2 = []
print(timeit("for i in range(0, np.size(data)): data2.append(func2(data[i]))", **kwds))
data3 = []
print(timeit("for i in range(0, np.size(data)): data3.append(func1(data[i]))", **kwds))

0.06953751016408205
0.957529284991324
15.591511018108577

现在,它与func2 一起工作的事实、文档和流行的自适应集成方案的工作方式都表明quad 一个接一个地用标量参数调用它的被积函数,这可以解释你的观察。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-01
    • 2016-12-20
    • 2016-07-24
    • 2017-10-25
    • 1970-01-01
    • 2014-11-28
    • 1970-01-01
    相关资源
    最近更新 更多