一些numpy / scipy代码的优化

时间:2014-08-08 20:12:40

标签: optimization numpy scipy

我试图优化一些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中按照我的方式返回多个值是个好主意吗?

1 个答案:

答案 0 :(得分:2)

如果我完全理解您的a0t0不是优化的一部分,那么您只能优化tt。但是,在lineSphericalDist内,您调用self.fun(t0)。您可以在lineSphericalDist之外预先计算该数量,这会将对self.fun的调用次数减半...

您还可以在lineSphericalDist之外计算betanp.sin(beta - t0)np.sqrt(x0**2 + y0**2),只留下在lineSphericalDist中真正依赖tt的位。

最后,为什么self.fun计算4个值,如果只使用3个或2个?这是你的瓶颈功能,让它只计算严格必要的......