将 cython 函数与 cython 方法传递给 scipy.integrate [英] Passing a cython function vs a cython method to scipy.integrate

查看:34
本文介绍了将 cython 函数与 cython 方法传递给 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

  1. 使用在类外定义的 cython 被积函数:integrate_other(好的!)
  2. 使用在类中定义的 cython 被积函数:integrate_self(产生错误)
  3. 将类中定义的 cython 被积函数包装在类中定义的 python 函数中:integrate_wrap_self(好的!)
  1. Using a cython integrand function defined outside the class: integrate_other (ok!)
  2. Using a cython integrand function defined inside the class: integrate_self (produces error)
  3. 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() 正好需要 2 个位置参数(给定 1 个)暗示问题出在我认为使用 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆