Я выполняю некоторые тесты производительности по варианту генератора простых чисел из http://docs.cython.org/src/tutorial/numpy.html. Приведенные ниже показатели производительности: kmax = 1000
Реализация Pure Python, работающая в CPython: 0.15s
Реализация Pure Python, работающая в Cython: 0.07s
def primes(kmax):
p = []
k = 0
n = 2
while k < kmax:
i = 0
while i < k and n % p[i] != 0:
i = i + 1
if i == k:
p.append(n)
k = k + 1
n = n + 1
return p
Реализация Pure Python + Numpy, работающая в CPython: 1.25s
import numpy
def primes(kmax):
p = numpy.empty(kmax, dtype=int)
k = 0
n = 2
while k < kmax:
i = 0
while i < k and n % p[i] != 0:
i = i + 1
if i == k:
p[k] = n
k = k + 1
n = n + 1
return p
Реализация Cython с использованием int *: 0.003s
from libc.stdlib cimport malloc, free
def primes(int kmax):
cdef int n, k, i
cdef int *p = <int *>malloc(kmax * sizeof(int))
result = []
k = 0
n = 2
while k < kmax:
i = 0
while i < k and n % p[i] != 0:
i = i + 1
if i == k:
p[k] = n
k = k + 1
result.append(n)
n = n + 1
free(p)
return result
Вышеприведенное замечательно, но выглядит ужасно, поскольку оно хранит две копии данных... поэтому я попытался переопределить его:
Cython + Numpy: 1.01s
import numpy as np
cimport numpy as np
cimport cython
DTYPE = np.int
ctypedef np.int_t DTYPE_t
@cython.boundscheck(False)
def primes(DTYPE_t kmax):
cdef DTYPE_t n, k, i
cdef np.ndarray p = np.empty(kmax, dtype=DTYPE)
k = 0
n = 2
while k < kmax:
i = 0
while i < k and n % p[i] != 0:
i = i + 1
if i == k:
p[k] = n
k = k + 1
n = n + 1
return p
Вопросы:
- Почему массив numpy настолько невероятно медленнее, чем список python, при запуске на CPython?
- Что я сделал неправильно в реализации Cython + Numpy? cython, очевидно, НЕ обрабатывает массив numpy как int [], как и должно быть.
-
как мне сделать массив numpy для int *? Ниже не работает
cdef numpy.nparray a = numpy.zeros(100, dtype=int) cdef int * p = <int *>a.data