我试图优化一些python代码,它使用scipy.optimize.root
进行rootfinding。
cProfile告诉我,程序大部分时间都在评估optimize.root
调用的函数:
例如总执行时间为80秒,58 {s}花费在lineSphericalDist
fun
贡献54s(以及约215,000个电话):
Fri Aug 8 21:09:32 2014 profile2
12796193 function calls (12617458 primitive calls) in 82.707 seconds
Ordered by: cumulative time
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.005 0.005 82.710 82.710 BilliardsNumpyClass.py:6(<module>)
1 0.033 0.033 64.155 64.155 BilliardsNumpyClass.py:446(traceAll)
100 1.094 0.011 63.549 0.635 BilliardsNumpyClass.py:404(trace)
91333 7.226 0.000 58.804 0.001 BilliardsNumpyClass.py:244(lineSphericalDist)
214667 49.436 0.000 54.325 0.000 BilliardsNumpyClass.py:591(fun)
...
这里的optimize.root调用some trace
:
...
res = optimize.root(self.lineSphericalDist, [tguess], args=(t0, a0), method='lm')
...
该函数包含一些基本的三角函数:
def lineSphericalDist(self, tt, t0, a0):
x0,y0,vnn = self.fun(t0)[0:3]
beta = np.pi + t0 + a0 - vnn
l = np.sin(beta - t0)/np.sin(beta - tt)
x2,y2 = self.fun(tt)[0:2]
return np.sqrt(x0**2+y0**2)*l-np.sqrt(x2**2+y2**2)
在最简单的情况下,乐趣是:
def fun(self,t):
return self.r*np.cos(t),self.r*np.sin(t),np.pi/2.,np.mod(t+np.pi/2., np.pi*2.)
有没有办法加快这个速度(tguess已经是一个非常好的起始值)?我做错了什么?例如在fun
中按照我的方式返回多个值是个好主意吗?
答案 0 :(得分:2)
如果我完全理解您的a0
和t0
不是优化的一部分,那么您只能优化tt
。但是,在lineSphericalDist
内,您调用self.fun(t0)。您可以在lineSphericalDist之外预先计算该数量,这会将对self.fun的调用次数减半...
您还可以在lineSphericalDist之外计算beta
,np.sin(beta - t0)
和np.sqrt(x0**2 + y0**2)
,只留下在lineSphericalDist中真正依赖tt
的位。
最后,为什么self.fun计算4个值,如果只使用3个或2个?这是你的瓶颈功能,让它只计算严格必要的......