Creating Small Arrays In Cython Takes A Humongous Amount Of Time
Solution 1:
There is a discussion of this on the Cython list that might have some useful suggestions: https://groups.google.com/forum/#!topic/cython-users/CwtU_jYADgM
Generally though I try to allocate small arrays outside of Cython, pass them in and re-use them in subsequent calls to the method. I understand that this is not always an option.
Solution 2:
Creating np.empty
inside the Cython function has some overhead as you already saw. Here you will see an example about how to create the empty array and pass it to the Cython module in order to fill with the correct values:
n=10
:
numpy.searchsorted:1.30574745517cythonO(1):3.28732016088cythonnoarraydeclaration1.54710909596
n=100
:
numpy.searchsorted:4.15200545373cythonO(1):13.7273431067cythonnoarraydeclaration11.4186086744
As you already pointed out, the numpy
version scales better since it is O(len(u)*long(len(a)))
and this algorithm here is O(len(u)*len(a))
...
I also tried to use Memoryview, basically changing np.ndarray[double, ndim=1]
by double[:]
, but the first option was faster in this case.
The new .pyx
file is:
from __future__ import division
import numpy as np
cimport numpy as np
cimport cython
@cython.boundscheck(False)@cython.wraparound(False)defJustLoop(np.ndarray[double, ndim=1] a, np.ndarray[double, ndim=1] u,
np.ndarray[int, ndim=1] r):
cdefint i,j
for j inrange(u.shape[0]):
if u[j] < a[0]:
r[j] = 0continueif u[j] > a[a.shape[0]-1]:
r[j] = a.shape[0]-1continuefor i inrange(1, a.shape[0]):
if u[j] >= a[i-1] and u[j] < a[i]:
r[j] = i
break@cython.boundscheck(False)@cython.wraparound(False)defWithArray(np.ndarray[double, ndim=1] a, np.ndarray[double, ndim=1] u):
cdefnp.ndarray[np.int_t, ndim=1] r=np.empty(u.shape[0],dtype=int)
cdefint i,j
for j inrange(u.shape[0]):
if u[j] < a[0]:
r[j] = 0continueif u[j] > a[a.shape[0]-1]:
r[j] = a.shape[0]-1continuefor i inrange(1, a.shape[0]):
if u[j] >= a[i-1] and u[j] < a[i]:
r[j] = i
breakreturn r
The new .py
file:
import numpy
import subprocess
import timeit
#Compile the cython modules before importing them
subprocess.call(['python', 'setup.py', 'build_ext', '--inplace'])
from test import *
sstr="""
import test
import numpy
u=numpy.random.random(10)
a=numpy.random.random(10)
a=numpy.cumsum(a)
a/=a[-1]
a.sort()
r = numpy.empty(u.shape[0], dtype=int)
"""print"numpy.searchsorted:",timeit.timeit('numpy.searchsorted(a,u)',sstr)
print"cython O(1):",timeit.timeit('test.WithArray(a,u)',sstr)
print"cython no array declaration",timeit.timeit('test.JustLoop(a,u,r)',sstr)
Post a Comment for "Creating Small Arrays In Cython Takes A Humongous Amount Of Time"