将 cython 函数与 cython 方法传递给 scipy.integrate
Passing a cython function vs a cython method to scipy.integrate
我正在尝试研究如何使用 cython 来加速涉及在我定义的 class 中完成的积分的计算。我试图更好地理解 cython 如何与用户定义的 python classes 一起工作。我想详细了解为什么会出现下面描述的错误。
我在名为 ex.pyx
的文件中有以下 cython 代码
from libc.math cimport log
from libc.math cimport sqrt
import scipy.integrate as integ
cdef double integrand_outside(double x):
"""Cython: integrand outside the class"""
cdef double f = log(x) / sqrt(x)
return f
cdef class CalcSomething(object):
def integrate_other(self, double a, double b):
"""This does the integral with the integrand outside the class"""
return integ.quad(integrand_outside, a, b)[0]
def integrate_self(self, double a, double b):
"""This does the integral with the integrand inside the class"""
return integ.quad(self._integrand, a, b)[0]
def integrate_wrap_self(self, double a, double b):
"""This does the integral with the integrand inside the class"""
return integ.quad(self.wrap_integrand, a, b)[0]
def wrap_integrand(self, double x):
"""Python method that wraps _integrand"""
return self._integrand(x)
cdef double _integrand(self, double x):
"""Cython: integrand inside the class"""
cdef double f = log(x) / sqrt(x)
return f
它显示了从 class
中调用 scipy.integrate.quad
的三种方法
- 使用在 class 之外定义的 cython 被积函数:
integrate_other
(好的!)
- 使用 class 中定义的 cython 被积函数:
integrate_self
(产生错误)
- 将 class 中定义的 cython 被积函数包装在 class 中定义的 python 函数中:
integrate_wrap_self
(好!)
上面的 cython 代码可以正常编译。现在我调用这些集成方法中的每一个,例如
import ex
calcSomething = ex.CalcSomething()
a = 0.001
b = 0.1
calcSomething.integrate_other(a,b) # works
calcSomething.integrate_wrap_self(a,b) # works
calcSomething.integrate_self(a,b) # doesn't work
这是回溯:
Traceback (most recent call last):
File "../examples/example.py", line 10, in <module>
print "integrate self =", calcSomething.integrate_self(a,b) # doesn't work
File "ex.pyx", line 17, in ex.CalcSomething.integrate_self (ex.c:989)
return integ.quad(self._integrand, a, b)[0]
File "/home/alex/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/scipy/integrate/quadpack.py", line 281, in quad
retval = _quad(func,a,b,args,full_output,epsabs,epsrel,limit,points)
File "/home/alex/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/scipy/integrate/quadpack.py", line 345, in _quad
return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit)
File "stringsource", line 30, in cfunc.to_py.__Pyx_CFunc_double____CalcSomething____double___to_py.wrap (ex.c:1560)
TypeError: wrap() takes exactly 2 positional arguments (1 given)
这是我的问题:
为什么 scipy.integrate
可以作为 cython 函数或 python 方法传递(所以现在将实例作为第一个参数)而不是作为 cython 方法传递?错误:
TypeError: wrap() takes exactly 2 positional arguments (1 given)
暗示问题出在我认为用 cython 方法传递的实例参数?
这个错误是我对cython怎么做的理解有误,还是scipy
的限制?
如果我想通过赛通?披露:真正的代码将调用 GSL 集成函数,而不是 scipy
.
从 hpaulj 上面的帮助:答案是 _integrand
方法需要声明 cpdef
而不是 cdef
cpdef double _integrand(self, double x):
"""Cython: integrand inside the class"""
cdef double f = log(x) / sqrt(x)
return f
我正在尝试研究如何使用 cython 来加速涉及在我定义的 class 中完成的积分的计算。我试图更好地理解 cython 如何与用户定义的 python classes 一起工作。我想详细了解为什么会出现下面描述的错误。
我在名为 ex.pyx
from libc.math cimport log
from libc.math cimport sqrt
import scipy.integrate as integ
cdef double integrand_outside(double x):
"""Cython: integrand outside the class"""
cdef double f = log(x) / sqrt(x)
return f
cdef class CalcSomething(object):
def integrate_other(self, double a, double b):
"""This does the integral with the integrand outside the class"""
return integ.quad(integrand_outside, a, b)[0]
def integrate_self(self, double a, double b):
"""This does the integral with the integrand inside the class"""
return integ.quad(self._integrand, a, b)[0]
def integrate_wrap_self(self, double a, double b):
"""This does the integral with the integrand inside the class"""
return integ.quad(self.wrap_integrand, a, b)[0]
def wrap_integrand(self, double x):
"""Python method that wraps _integrand"""
return self._integrand(x)
cdef double _integrand(self, double x):
"""Cython: integrand inside the class"""
cdef double f = log(x) / sqrt(x)
return f
它显示了从 class
中调用scipy.integrate.quad
的三种方法
- 使用在 class 之外定义的 cython 被积函数:
integrate_other
(好的!) - 使用 class 中定义的 cython 被积函数:
integrate_self
(产生错误) - 将 class 中定义的 cython 被积函数包装在 class 中定义的 python 函数中:
integrate_wrap_self
(好!)
上面的 cython 代码可以正常编译。现在我调用这些集成方法中的每一个,例如
import ex
calcSomething = ex.CalcSomething()
a = 0.001
b = 0.1
calcSomething.integrate_other(a,b) # works
calcSomething.integrate_wrap_self(a,b) # works
calcSomething.integrate_self(a,b) # doesn't work
这是回溯:
Traceback (most recent call last):
File "../examples/example.py", line 10, in <module>
print "integrate self =", calcSomething.integrate_self(a,b) # doesn't work
File "ex.pyx", line 17, in ex.CalcSomething.integrate_self (ex.c:989)
return integ.quad(self._integrand, a, b)[0]
File "/home/alex/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/scipy/integrate/quadpack.py", line 281, in quad
retval = _quad(func,a,b,args,full_output,epsabs,epsrel,limit,points)
File "/home/alex/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/scipy/integrate/quadpack.py", line 345, in _quad
return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit)
File "stringsource", line 30, in cfunc.to_py.__Pyx_CFunc_double____CalcSomething____double___to_py.wrap (ex.c:1560)
TypeError: wrap() takes exactly 2 positional arguments (1 given)
这是我的问题:
为什么
scipy.integrate
可以作为 cython 函数或 python 方法传递(所以现在将实例作为第一个参数)而不是作为 cython 方法传递?错误:TypeError: wrap() takes exactly 2 positional arguments (1 given)
暗示问题出在我认为用 cython 方法传递的实例参数?这个错误是我对cython怎么做的理解有误,还是
scipy
的限制?如果我想通过赛通?披露:真正的代码将调用 GSL 集成函数,而不是
scipy
.
从 hpaulj 上面的帮助:答案是 _integrand
方法需要声明 cpdef
而不是 cdef
cpdef double _integrand(self, double x):
"""Cython: integrand inside the class"""
cdef double f = log(x) / sqrt(x)
return f