问题描述
我想减少Scipy的odeint解微分
方程所需的时间。
I would like to lower the time Scipy's odeint takes for solving a differentialequation.
要练习,我使用了作为模板。因为odeint使用函数 f
作为参数,所以我将此函数编写为静态类型的Cython版本,并希望
的odeint运行时间会大大减少。
To practice, I used the example covered in Python in scientific computations as template. Because odeint takes a function f
as argument, I wrote this function as a statically typed Cython version and hopedthe running time of odeint would decrease significantly.
函数 f
包含在名为 ode.pyx $ c $的文件中c>如下:
import numpy as np
cimport numpy as np
from libc.math cimport sin, cos
def f(y, t, params):
cdef double theta = y[0], omega = y[1]
cdef double Q = params[0], d = params[1], Omega = params[2]
cdef double derivs[2]
derivs[0] = omega
derivs[1] = -omega/Q + np.sin(theta) + d*np.cos(Omega*t)
return derivs
def fCMath(y, double t, params):
cdef double theta = y[0], omega = y[1]
cdef double Q = params[0], d = params[1], Omega = params[2]
cdef double derivs[2]
derivs[0] = omega
derivs[1] = -omega/Q + sin(theta) + d*cos(Omega*t)
return derivs
然后我创建一个文件 setup.py
来构成函数:
I then create a file setup.py
to complie the function:
from distutils.core import setup
from Cython.Build import cythonize
setup(ext_modules=cythonize('ode.pyx'))
求解微分方程的脚本(还包含 f
的Python
版本)称为 solveODE.py
,其外观为:
The script solving the differential equation (also containing the Pythonversion of f
) is called solveODE.py
and looks as:
import ode
import numpy as np
from scipy.integrate import odeint
import time
def f(y, t, params):
theta, omega = y
Q, d, Omega = params
derivs = [omega,
-omega/Q + np.sin(theta) + d*np.cos(Omega*t)]
return derivs
params = np.array([2.0, 1.5, 0.65])
y0 = np.array([0.0, 0.0])
t = np.arange(0., 200., 0.05)
start_time = time.time()
odeint(f, y0, t, args=(params,))
print("The Python Code took: %.6s seconds" % (time.time() - start_time))
start_time = time.time()
odeint(ode.f, y0, t, args=(params,))
print("The Cython Code took: %.6s seconds ---" % (time.time() - start_time))
start_time = time.time()
odeint(ode.fCMath, y0, t, args=(params,))
print("The Cython Code incorpoarting two of DavidW_s suggestions took: %.6s seconds ---" % (time.time() - start_time))
然后我运行:
python setup.py build_ext --inplace
python solveODE.py
在终端中。
python版本的时间约为0.055秒,
,而Cython版本的时间约为0.04秒。
The time for the python version is approximately 0.055 seconds,whilst the Cython version takes roughly 0.04 seconds.
有人建议我改进使用Cython求解
微分方程的尝试,最好不要修改odeint例程本身吗?
Does somebody have a recommendation to improve on my attempt of solving thedifferential equation, preferably without tinkering with the odeint routine itself, with Cython?
编辑
我将DavidW的建议合并到了两个文件中。 c> ode.pyx 和 solveODE.py
只需大约0.015秒即可运行带有这些建议的代码。
I incorporated DavidW's suggestion in the two files ode.pyx
and solveODE.py
It took only roughly 0.015 seconds to run the code with these suggestions.
推荐答案
最简单的更改(可能会为您带来很多好处)是使用C数学库 sin
和 cos
用于对单个数字(而不是数字)进行运算。调用 numpy
以及花费时间来解决它不是一个数组的代价相当高。
The easiest change to make (which will probably gain you a lot) is to use the C math library sin
and cos
for operations on single numbers instead of number. The call to numpy
and the time spent working out that it isn't an array is fairly costly.
from libc.math cimport sin, cos
# later
-omega/Q + sin(theta) + d*cos(Omega*t)
我很想为输入 d $ c分配类型$ c>(无需更改接口即可轻松键入其他任何输入):
I'd be tempted to assign a type to the input d
(none of the other inputs are easily typed without changing the interface):
def f(y, double t, params):
我想我也将像在Python版本中一样返回一个列表。我认为使用C数组不会带来很多收益。
I think I'd also just return a list like you do in your Python version. I don't think you gain a lot by using a C array.
这篇关于如何很好地使用Cython更快地求解微分方程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!