Я сделал функцию для оптимизации на Python (назовем ее optimizer
). Он требует, чтобы функция была оптимизирована (назовем ее objective
) в качестве одного из аргументов функции. objective
- это функция, которая принимает одномерный np.ndarray
и возвращает номер float
(который совпадает с double
в C++?).
Я прочитал этот Почта, но не уверен, действительно ли это та же проблема, что и у меня, и когда я использую 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
Я хочу знать, можно ли набрать objective
, чтобы код работал быстрее.
Я получаю сообщение об ошибке
Cannot convert Python object argument to type 'f_type'
что, я думаю, имеет гораздо больше смысла, чем тот, который вы утверждаете, - вы пытаетесь передать объект Python в функцию. Убедитесь, что сообщения об ошибках, о которых вы сообщаете, действительно генерируются вашим кодом. Ваше описание типов, которые принимает 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())
работает должным образом (и со скоростью Cython); example_function(PyFPtr(lambda x: x[0]))
работает как положено (без скорости Cython в вызываемом); example_function(PyFPtr(lambda x: "hello"))
, как и ожидалось, выдает ошибку типа.
нужно больше кода, чтобы понять вашу проблему.