NumPy arrays

NumPy arrays can be used as normal Python objects in Cython using their already optimized broadcasted operations. However, Cython provides a numpy module with better support for direct iteration.

When we normally access an element of a NumPy array, a few other operations take place at the interpreter level causing a major overhead. Cython can bypass those operations and checks by acting directly on the underlying memory area used by NumPy arrays, and thus obtaining impressive performance gains.

NumPy arrays can be declared as the ndarray data type. To use the data type in our code, we first need to cimport the numpy Cython module (which is not the same as the Python NumPy module). We will bind the module to the c_np variable to make the difference with the Python numpy module more explicit:

    cimport numpy as c_np
import numpy as np

We can now declare a NumPy array by specifying its type and the number of dimensions between square brackets (this is called buffer syntax). To declare a two-dimensional array of type double, we can use the following code:

    cdef c_np.ndarray[double, ndim=2] arr 

Access to this array will be performed by directly operating on the underlying memory area; the operation will avoid stepping into the interpreter, giving us a tremendous speed boost.

In the next example, we will show the usage of typed numpy arrays and compare them with the normal Python version.

We first write the numpy_bench_py function that increments each element of py_arr. We declare the i index as an integer so that we avoid the for-loop overhead:

    %%cython 
import numpy as np
def numpy_bench_py():
py_arr = np.random.rand(1000)
cdef int i
for i in range(1000):
py_arr[i] += 1

Then, we write the same function using the ndarray type. Note that after we define the c_arr variable using c_np.ndarray, we can assign to it an array from the numpy Python module:

    %%cython 
import numpy as np
cimport numpy as c_np

def numpy_bench_c():
cdef c_np.ndarray[double, ndim=1] c_arr
c_arr = np.random.rand(1000)
cdef int i

for i in range(1000):
c_arr[i] += 1

We can time the results using timeit, and we can see how the typed version is 50x faster:

    %timeit numpy_bench_c() 
100000 loops, best of 3: 11.5 us per loop
%timeit numpy_bench_py()
1000 loops, best of 3: 603 us per loop
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.90.182