【问题标题】:Is it possible to pass a cython function as argument to a scipy function?是否可以将 cython 函数作为参数传递给 scipy 函数?
【发布时间】:2012-10-11 20:06:03
【问题描述】:

Scipy 有许多函数可以接受 python 可调用来执行某些操作。特别是,我正在使用一个数学优化函数scipy.optimize.leastsq,它接受 Python 可调用作为目标函数参数。在最小化过程中,leastsq 可以多次调用此目标函数。

我的分析表明,很多时间都花在了该目标函数上。我已经使用 Cython 加速了该功能的某些部分。但是,该函数本身仍然是一个 Python 函数,并且重复调用它(如 leastsq 所做的那样)有一些开销。

如果函数是 Cython 函数(使用 cdef 而不是 def),我认为我可以进一步提高速度。因此,我在 Cython 扩展中调用了 leastsq,并将 Cython 目标函数传递给它。但是当我这样做时 我在 leastsq 调用时遇到编译错误:

Cannot convert 'object (object, object, object)' to Python object

有没有办法将 Cython 函数作为参数传递给这些需要 python 可调用对象的 Scipy 函数?

或者,就我而言,有没有办法访问底层 leastsq 实现并将 Cython 目标函数传递给它?

【问题讨论】:

    标签: scipy cython


    【解决方案1】:

    目前无法传入cdef 函数。将回调函数传递给底层的 Fortran 代码也是不可能的,因为它是用 f2py 包装的,它不知道 Cython。

    你可以做的是:

    • 将您的函数编写为 Cython 的 def 函数。这些可以传递给所有 Scipy 的例程。这不会消除使用 Python 的回调机制带来的额外函数调用开销(这可能并不重要!),但您可以加快函数的实现,这可能就足够了。只要记住 cdef 出现的变量,就像编写 Cython 代码时一样。

    • 从 Scipy 或 netlib.org 复制 MINPACK 源代码,然后自己直接使用。这通过将 Python 函数回调机制替换为低级机制来消除剩余的函数调用开销。

    (已经讨论过添加一个协议来传递低级函数指针正是为了这个目的,任何需要它的基于 Python 的系统都可以采用它,但是 AFAIK 的设计还没有完成,并且未在 Cython 和 Scipy 中实现。)

    【讨论】:

    • 谢谢。我已经完成了第一个建议,将我的目标函数保持为 python 函数并加速其在 cython 中的代码。我得到了一些加速,但并没有太多,因为原始代码已经大部分都用 numpy 向量化了。关于第二个建议,我一直在挖掘一段时间,试图在 _minpack.pyd 中调用 lmdif 并使用签名 cdef int raw_multipack_lm_function(int *m, int *n, double *x, double *fvec, int *iflag) 传递我的目标函数,但我有很多错误,我被卡住了,我想知道你是否可以向我推荐一些如何做到这一点的例子。
    • 我手头没有例子。但是,我建议您重新检查该时间实际上还没有花在函数内,例如。只需通过 time.time()。我希望使用第二个选项的性能改进不是很重要,除非您的函数的评估速度相当快。
    • 好的。我已经测量了在目标函数中花费了多长时间,相对于最小平方优化需要多长时间。我花了大约 69% 的时间在目标函数上进行测试,结果是 41 个目标函数评估。我想花在调用开销上的时间一定是剩余 31% 的一小部分。我将使用 python 调用保持原样,并专注于加速目标函数。感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-22
    • 2013-01-27
    • 1970-01-01
    • 2021-07-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多