代码之家  ›  专栏  ›  技术社区  ›  Physicist

如何在cython的函数参数中键入函数

  •  1
  • Physicist  · 技术社区  · 8 年前

    optimizer ). 它需要对函数进行优化(我们称之为 objective )作为函数参数之一。 客观的 是一个接受一维 np.ndarray 并返回一个 float 编号(与 double

    我读过这个 post ,但我不确定它是否真的是同一个问题,当我使用 ctypedef int (*f_type)(int, str) Cannot convert 'f_type' to Python object 在编译过程中。它只对C函数有效吗?如何键入python函数?

    编辑:我的代码看起来像:

    cpdef optimizer(objective, int num_particle, int dim,
                 np.ndarray[double, ndim=1] lower_bound,
                 np.ndarray[double, ndim=1] upper_bound):
    
        cdef double min_value
        cdef np.ndarray[double, ndim=2] positions = np.empty((num_particle,dim), dtype=np.double)
        cdef np.ndarray[double, ndim=1] fitness = np.empty(num_particle, dtype=np.double)
        cdef int i, j
    
        # do lots of stuff not shown here
        # involve the following code:
        for i in range(num_particle):
            fitness[i] = objective(positions[i])
    
        return min_value
    

    我想知道是否可以打字 使代码运行更快。

    1 回复  |  直到 8 年前
        1
  •  5
  •   DavidW    8 年前

    我收到了错误信息

    Cannot convert Python object argument to type 'f_type'

    objective


    但是,一般来说:不,你不能给你的目标函数一个类型说明符来加速它。一般的Python可调用函数比C函数指针携带更多的信息(例如引用计数、任何闭包捕获变量的细节等)。

    一种可能的替代方法是继承 cdef class cdef 功能,因此您至少可以在特定情况下获得适当的性能:

    # an abstract function pointer class
    cdef class FPtr:
        cdef double function(self,double[:] x) except? 0.0:
            # I'm assuming you might want to pass exceptions back to Python - use 0.0 to indicate that there might have been an error
            raise NotImplementedError()
    
    # an example class that inherits from the abstract pointer type    
    cdef class SumSq(FPtr):
        cdef double function(self,double[:] x) except? 0.0:
            cdef double sum=0.0
            for i in range(x.shape[0]):
                sum += x[i]**2
            return sum
    
    # an example class that just wraps a Python callable
    # this will be no faster, but makes the code generically usable
    cdef class PyFPtr(FPtr):
        cdef object f
        def __init__(self,f):
            self.f = f
    
        cdef double function(self,double[:] x) except? 0.0:
            return self.f(x) # will raise an exception if the types don't match
    
    def example_function(FPtr my_callable):
        import numpy as np
        return my_callable.function(np.ones((10,)))
    

    使用这个 example_function(SumSq()) example_function(PyFPtr(lambda x: x[0])) 按预期工作(可调用中没有Cython速度); example_function(PyFPtr(lambda x: "hello"))