我有一个解决ODE的python算法。现在我注意到这段代码对于几个不同的输入参数非常慢。因此,我分析了代码,结果得到了:
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.004 0.004 429.032 429.032 gnlse.py:153(perform_simulation)
2 0.001 0.000 429.017 214.508 _ode.py:564(integrate)
2 0.000 0.000 429.016 214.508 _ode.py:381(integrate)
2 18.985 9.492 429.016 214.508 _ode.py:1013(run)
52007 22.260 0.000 410.031 0.008 _ode.py:495(_wrap)
52007 188.766 0.004 387.243 0.007 gnlse.py:234(GNLSE_RHS)
208033 1.300 0.000 173.272 0.001 fftpack.py:46(_raw_fft)
104018 18.316 0.000 108.077 0.001 fftpack.py:195(ifft)
104015 0.857 0.000 90.410 0.001 fftpack.py:100(fft)
104015 85.626 0.001 85.626 0.001 {numpy.fft.fftpack_lite.cfftf}
104018 85.607 0.001 85.607 0.001 {numpy.fft.fftpack_lite.cfftb}
29108 25.776 0.001 25.776 0.001 {min}
530887 3.275 0.000 3.275 0.000 {numpy.core.multiarray.array}
104034 2.522 0.000 2.522 0.000 {method 'astype' of 'numpy.ndarray' objects}
算法的哪一部分可以最佳地优化(可以在没有基于cProfile测量的整个代码的情况下回答?)?根据数据我会说GNLSE_RHS
函数,在此函数花费的总时间之后是最重要的
在此函数中,调用fft
- 函数(每次调用四次)。让它们更快而不是改进GNLSE_RHS
中的算法是否更有意义?
有问题的功能是
AT = np.fft.fft( np.multiply( AW , np.exp( simp['linop'] * z)))
IT = np.abs(AT)**2
if simp['raman'] == True:
RS = simp['dt'] * np.fft.fft( np.multiply( np.fft.ifft(IT), simp['RW'] ))
M = np.fft.ifft( np.multiply( AT,( (1-simp['fr'])*IT + simp['fr']*RS ) ) )
else:
M = np.fft.ifft( np.multiply( AT, IT))
return 1.0j * simp['gamma'] * np.multiply( simp['W'], np.multiply( M, np.exp( -simp['linop'] * z)) )
编辑:我不需要一个精确的算法,我宁愿知道哪个部分主要是对运行时间的影响,即提高哪个功能的速度最能提高整体速度?
答案 0 :(得分:0)
我认为你没事。 GNLSE_RHS
显然是你的瓶颈。
52007 188.766 0.004 387.243 0.007 gnlse.py:234(GNLSE_RHS)
问题 - 您的percall
非常短暂。我猜测GNLSE_RHS
是由scipy
包裹的fortran函数。如果是这样,那么精简它就很难了。
我解决薛定谔方程(主要是虚时间传播)的方法一直是在用C语言选择最终实现之前,用Python开发我对算法的理解。
答案 1 :(得分:-2)
使用DRY (Don't repeat yourself)原则。寻找重复的代码并将它们变成变量。
例如,您不止一次调用simp['linop']
和simp['fr']
,这是每次字典查找。相反,请设置linop_z = simp['linop'] * z
一次,然后每次使用linop_z
,同样适用于fr = simp['fr']
。
还需要展开你的等式,寻找常见的乘数等等。