加速python代码(多重积分计算)

时间:2013-06-28 08:22:09

标签: python integration mpmath

有没有办法加速这段代码:

import mpmath as mp
import numpy as np
from time import time as epochTime

def func(E):
    f = lambda theta: mp.sin(theta) * mp.exp(E * (mp.cos(theta**2) + \
                                                  mp.cos(theta)**2))
    return f

start = epochTime()
mp.mp.dps = 15
mp.mp.pretty = True

E = np.linspace(0, 10, 200)
ints = [mp.quadgl(func(e), [0, mp.pi]) for e in E] # Main Job
print ('Took:{:.3}s'.format(epochTime() - start))

2 个答案:

答案 0 :(得分:4)

运行你的代码,我把它计时到5.84s

使用Memoize并简化表达式:

cos = Memoize(mp.cos)
sin = Memoize(mp.sin)

def func(E):
    def f(t):
        cost = cos(t)
        return sin(t) * mp.exp(E * (cos(t*t) + cost*cost))
    return f

我第一次将它降低到3.25秒,并在下一次迭代中降低到2.8秒。

(更好的方法可能是使用标准库中的lru_cache,但我没有尝试计时。)

如果您多次运行类似的代码,Memoize() funcf都可能是明智的,因此计算变得微不足道(~0.364s)。

mp替换为math cos / sin / exp,我得到了~1.3s,现在记忆会使性能变差,出于某种原因(~1.5s,我猜是查找时间变得占主导地位。)

答案 1 :(得分:1)

通常,您希望尽可能避免调用sin,cos,exp,ln等超越函数,尤其是在像“被积函数”这样的“热”函数中。

  • 将x ** 2替换为x * x(通常x ** 2称为泛型=慢速取幂函数)
  • 将变量用于多次使用的“昂贵”中间词
  • 转换你的等式以减少或消除超越函数
  • 典型参数值的特殊情况。整数指数是常见的候选人。
  • 预先计算所有不变的东西,espc。参数化函数

对于特定示例,您可以替换z = cos(theta)。它是dz = -sin(theta)dtheta。您的被积函数变为

-exp(E*(z^2 + cos(arccos(z)^2))

为您节省一些超越函数调用。边界[0,pi]变为[1,-1]。还要避免x ** 2,最好使用x * x。

完整代码:

import mpmath as mp
import numpy as np
from time import time as epochTime

def func(E):
    def f(z):
        acz = mp.acos(z)
        return -mp.exp(E * (mp.cos(acz*acz) + z*z))
    return f

start = epochTime()
mp.mp.dps = 15
mp.mp.pretty = True

E = np.linspace(0, 10, 200)
ints = [mp.quadgl(func(e), [1.0, -1.0]) for e in E] # Main Job
print ('Took:{:.3}s'.format(epochTime() - start))