有没有办法加速这段代码:
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))
答案 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()
func
和f
都可能是明智的,因此计算变得微不足道(~0.364s)。
将mp
替换为math
cos / sin / exp,我得到了~1.3s,现在记忆会使性能变差,出于某种原因(~1.5s,我猜是查找时间变得占主导地位。)
答案 1 :(得分:1)
通常,您希望尽可能避免调用sin,cos,exp,ln等超越函数,尤其是在像“被积函数”这样的“热”函数中。
对于特定示例,您可以替换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))