Я хочу использовать Cython, чтобы уменьшить время, необходимое для добавления двух массивов (поэлементно) без с использованием Numpy массивов. Базовый c Python подход, который я нашел самым быстрым, заключается в использовании списочного понимания следующим образом:
def add_arrays(a,b):
return [m + n for m,n in zip(a,b)]
Мой подход к Cython немного сложнее и выглядит следующим образом:
from array import array
from libc.stdlib cimport malloc
from cython cimport boundscheck,wraparound
@boundscheck(False)
@wraparound(False)
cpdef add_arrays_Cython(int[:] Aarr, int[:] Barr):
cdef size_t i, I
I = Aarr.shape[0]
cdef int *Carr = <int *> malloc(640000 * sizeof(int))
for i in range(I):
Carr[i] = Aarr[i]+Barr[i]
result_as_array = array('i',[e for e in Carr[:640000]])
return result_as_array
Обратите внимание, что я использую @boundscheck(False)
и @wraparound(False)
, чтобы сделать его еще быстрее. Кроме того, меня беспокоит очень большой массив (размер 640000), и я обнаружил, что он выходит из строя, если я просто использую cdef int Carr[640000]
, поэтому я использовал malloc()
, что решило эту проблему. Наконец, я возвращаю структуру данных в виде Python массива типа integer.
Для профилирования кода я запустил следующее:
a = array.array('i', range(640000)) #create integer array
b = a[:] #array to add
T=time.clock()
for i in range(20): add_arrays(a,b) #Python list comprehension approach
print(time.clock() - T)
> 6,33 секунды
T=time.clock()
for i in range(20): add_arrays_Cython(a,b) #Cython approach
print(time.clock() - T)
> 4,54 секунды
Очевидно, что основанный на Cython подход дает ускорение примерно на 30%. Я ожидал, что ускорение будет ближе к порядку или даже больше (как это происходит для Numpy).
Что я могу сделать, чтобы ускорить код Cython дальше? Есть ли очевидные узкие места в моем коде? Я новичок в Cython, поэтому я могу что-то неправильно понять.