通过cython函数与cython方法进行scipy.integrate [英] Passing a cython function vs a cython method to scipy.integrate
问题描述
我正在尝试研究如何使用cython加快涉及我定义的类中完成的集成的计算.我试图更好地了解cython如何与用户定义的python类一起工作.我想了解更多有关为什么发生以下所述错误的信息.
I am trying work out how to use cython to speed up a calculation involving integration that is done within a class I have defined. I'm trying to understand better how cython works with user-defined python classes. I'd like to understand more about why the error described below occurs.
我在名为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
它显示了从类中调用scipy.integrate.quad
的三种方式
It shows three ways of calling scipy.integrate.quad
from within a class
- 使用在类外部定义的cython积分函数:
integrate_other
(好!) - 使用在类
integrate_self
中定义的cython被积函数(产生错误) - 将在类内部定义的cython被整数函数包装在类内部定义的python函数中:
integrate_wrap_self
(确定!)
- Using a cython integrand function defined outside the class:
integrate_other
(ok!) - Using a cython integrand function defined inside the class:
integrate_self
(produces error) - Wrapping the cython integrand function defined inside the class in a python function defined inside the class:
integrate_wrap_self
(ok!)
上面的cython代码可以正常编译.现在,我将这些集成方法称为
The above cython code compiles fine. Now I call each of these integrate methods, e.g.
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方法传递的实例参数吗?
Why can
scipy.integrate
be passed as a cython function or a python method (so now with instance as first argument) but not as a cython method? The error:TypeError: wrap() takes exactly 2 positional arguments (1 given)
implies the issue is with the instance argument that is passed with the cython method I think?
此错误是由于我对cython的误解还是scipy
的局限性造成的?
Is this error coming from my misunderstanding of how to do cython, or a limitation of scipy
?
如果我想通过cython加快速度,我打算在类中计算积分(通过在类中也调用被积分函数)的计划是不好的解决方案吗?披露:实际代码将调用GSL集成函数,而不是scipy
.
Is my intended plan of calculating an integral within a class (by calling an integrand function also within the class) a poor solution if I want to speed up via cython? Disclosure: the real code will call GSL integration functions, not scipy
.
推荐答案
在hpaulj的帮助下:答案是_integrand
方法需要声明为cpdef
而不是cdef
From hpaulj's help above: the answer is the _integrand
method needs to be declared cpdef
not cdef
cpdef double _integrand(self, double x):
"""Cython: integrand inside the class"""
cdef double f = log(x) / sqrt(x)
return f
这篇关于通过cython函数与cython方法进行scipy.integrate的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!