Я экспериментирую с объектом Cython, где я хотел бы иметь возможность многократно обновлять его атрибуты в соответствии с некоторыми условиями. Фиктивный код ниже просто меняет атрибуты произвольно, чтобы продемонстрировать проблему, с которой я сталкиваюсь. Я запускаю этот пример в блокноте Jupyter.
%load_ext Cython
%%cython -a
cdef class A_cy:
cdef int[:] a, b
def __cinit__(self, a, b):
self.a = a
self.b = b
cpdef void swap_attributes_cy(int[:] x):
cdef:
Py_ssize_t i
A_cy container = A_cy(x, x)
int _a
for i in range(1000000):
_a = container.a
container.a = container.b
container.b = _a
При тестировании этого варианта на чистой версии python, т.е.
class A_py:
def __init__(self, a, b):
self.a = a
self.b = b
def swap_attributes_py(x):
container = A_py(x,x)
for i in range(1000000):
_a = container.a
container.a = container.b
container.b = _a
Эта версия Cython медленнее (на моей машине), чем python (~200ms
против ~150ms
). Однако , если я изменю тип атрибутов на int
, версия python останется неизменной, но версия Cython займет ~110ns
! Я изо всех сил пытаюсь понять, почему есть разница при попытке поменять memoryview
против int
? Нужно ли использовать malloc
, realloc
и free
для обмена представлениями памяти?
Редактировать
Если я использую cdef np.ndarray a, b
вместо cdef int[:] a, b
, версия Cython теперь принимает ~6.7ms
. Можно ли все же улучшить это?