Рассмотрим следующий код Cython:
cimport cython
cimport numpy as np
import numpy as np
@cython.boundscheck(False)
@cython.wraparound(False)
def test_memoryview(double[:] a, double[:] b):
cdef int i
for i in range(a.shape[0]):
a[i] += b[i]
@cython.boundscheck(False)
@cython.wraparound(False)
def test_numpy(np.ndarray[double, ndim=1] a, np.ndarray[double, ndim=1] b):
cdef int i
for i in range(a.shape[0]):
a[i] += b[i]
def test_numpyvec(a, b):
a += b
def gendata(nb=40000000):
a = np.random.random(nb)
b = np.random.random(nb)
return a, b
Запуск его в интерпретаторе дает (после нескольких прогонов, чтобы разогреть кеш):
In [14]: %timeit -n 100 test_memoryview(a, b)
100 loops, best of 3: 148 ms per loop
In [15]: %timeit -n 100 test_numpy(a, b)
100 loops, best of 3: 159 ms per loop
In [16]: %timeit -n 100 test_numpyvec(a, b)
100 loops, best of 3: 124 ms per loop
# See answer below :
In [17]: %timeit -n 100 test_raw_pointers(a, b)
100 loops, best of 3: 129 ms per loop
Я попробовал его с разными размерами набора данных и последовательно использовал векторизованную функцию NumPy быстрее, чем скомпилированный код Cython, в то время как я ожидал, что Cython будет на одном уровне с векторизованным NumPy с точки зрения производительности.
Я забыл оптимизацию в моем Cython-коде? Использует ли NumPy что-то (BLAS?), Чтобы сделать такие простые операции быстрее? Могу ли я повысить производительность этого кода?
Обновление:. Необработанная версия указателя находится на одном уровне с NumPy. Таким образом, очевидно, что некоторые издержки при использовании памяти или индексирования NumPy.