¿Cómo puedo usar Cython bien para resolver una ecuación diferencial más rápido?
Me gustaría reducir el tiempo que tarda la odeint de Scipy en resolver una ecuación diferencial.
Para practicar, utilicé el ejemplo cubierto enPython en computaciones científicas como plantilla Porque odeint toma una funciónf
Como argumento, escribí esta función como una versión Cython estáticamente tipada y esperaba que el tiempo de ejecución de odeint disminuyera significativamente.
La funciónf
está contenido en un archivo llamadoode.pyx
como sigue:
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
Luego creo un archivosetup.py
para completar la función:
from distutils.core import setup
from Cython.Build import cythonize
setup(ext_modules=cythonize('ode.pyx'))
El script que resuelve la ecuación diferencial (que también contiene la versión Python def
) se llamasolveODE.py
y se ve como:
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))
Entonces corro:
python setup.py build_ext --inplace
python solveODE.py
en la terminal
El tiempo para la versión de Python es de aproximadamente 0.055 segundos, mientras que la versión de Cython tarda aproximadamente 0.04 segundos.
¿Alguien tiene una recomendación para mejorar mi intento de resolver la ecuación diferencial, preferiblemente sin modificar la rutina odeint en sí, con Cython?
Editar
Incorporé la sugerencia de DavidW en los dos archivosode.pyx
ysolveODE.py
Solo tomó aproximadamente 0.015 segundos ejecutar el código con estas sugerencias.