On Tue, Jul 17, 2012 at 9:04 AM, Neal Becker <
ndbe...@gmail.com> wrote:
> Thanks for the suggestion, I now have:
>
> ----------------
> import numpy as np
> cimport numpy as np
> cimport cython # boundscheck decorator
>
> @cython.boundscheck(False)
> @cython.wraparound(False)
> def spread_cmplx (np.complex[:] x, np.complex[:] z, int s):
> cdef np.ndarray[np.complex, ndim=1, mode="c"] w = np.zeros([z.shape[0]],
> dtype=np.complex)
> cdef int i
> cdef int L = z.shape[0]
> for i in range (L):
> w[i] = x[i/s] * z[i]
> return w
> -------------
> But this gives runtime error:
>
> File "spread.pyx", line 10, in spread.spread_cmplx (spread.cpp:1786)
> cdef np.ndarray[np.complex, ndim=1, mode="c"] w = np.zeros([z.shape[0]],
> dtype=np.complex)
> ValueError: Buffer dtype mismatch, expected 'complex object' but got 'complex
> double'
Try np.ndarray[double complex, ndim=1, mode="c"]. Also, no need to
initialize it to zeros.
Interestingly, I was unable to get your 3x slowdown, though it was
slightly slower (which is worrisome for the efficiency of np.repeat(),
'cause I'd echo Bradley's sentiment that the Python one should drop
down to fast enough pure C). You can also be faster by avoiding the
division (division is quite expensive, even if you turn on cdivision.
- Robert
import numpy as np
s = 5; n = 100
x = np.arange(n, dtype=np.complex)
z = np.arange(s * n, dtype=np.complex)
timeit("pyspread(x, z, s)")
timeit("spread_cmplx(x, z, s)")
timeit("spread_cmplx_typed(x, z, s)")
timeit("spread_cmplx_no_div(x, z, s)")
625 loops, best of 3: 41.1 µs per loop
625 loops, best of 3: 41.4 µs per loop
625 loops, best of 3: 8.72 µs per loop
625 loops, best of 3: 6.19 µs per loop
---------
def pyspread (x, z, s):
return np.repeat (x, s) * z
import numpy as np
cimport numpy as np
cimport cython # boundscheck decorator
@cython.boundscheck(False)
@cython.wraparound(False)
def spread_cmplx (np.ndarray[double complex] x, np.ndarray[double
complex] z, int s):
cdef np.ndarray w = np.zeros([z.shape[0]], dtype=np.complex)
cdef int ix
cdef int L = z.shape[0]
for ix in range (L):
w[ix] = x[ix/s] * z[ix]
return w
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.cdivision(True)
def spread_cmplx_typed (np.ndarray[double complex] x,
np.ndarray[double complex] z, int s):
cdef np.ndarray[double complex, mode="c"] w =
np.ndarray([z.shape[0]], dtype=np.complex)
cdef int ix
cdef int L = z.shape[0]
for ix in range (L):
w[ix] = x[ix/s] * z[ix]
return w
@cython.boundscheck(False)
@cython.wraparound(False)
def spread_cmplx_no_div (np.ndarray[double complex] x,
np.ndarray[double complex] z, int s):
cdef np.ndarray[double complex, mode="c"] w =
np.ndarray([z.shape[0]], dtype=np.complex)
cdef int i, j, ix
cdef int L = z.shape[0]
for i in range (x.shape[0]):
for j in range(s):
ix = i*s + j
w[ix] = x[i] * z[ix]
return w