Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding arrays with cython slower than numpy?

I am just starting to learn cython, so please excuse my ignorance. Can cython improve on numpy for simply adding two arrays together? My very bad attempt at adding two arrays a + b to give a new array c is:

import numpy as np
cimport numpy as np

DTYPE = np.int
ctypedef np.int_t DTYPE_t

def add_arrays(np.ndarray[DTYPE_t, ndim=2] a, np.ndarray[DTYPE_t, ndim=2] b, np.ndarray[DTYPE_t, ndim=2] c):
    cdef int x = a.shape[0]
    cdef int y = a.shape[1]
    cdef int val_a
    cdef int val_b
    for j in range(x):
        for k in range(y):
            val_a = a[j][k]
            val_b = b[j][k]
            c[j][k] = val_a + val_b    
    return c

However this version is 700 times slower (*edit: than numpy) when these arrays are passed:

n = 1000 
a = np.ones((n, n), dtype=np.int)
b = np.ones((n, n), dtype=np.int)
c = np.zeros((n, n), dtype=np.int)

I am obviously missing something very big.

like image 652
kezzos Avatar asked May 08 '14 16:05

kezzos


2 Answers

The problem is that you are indexing the 2-D array like c[j][k] when actually you should do c[j,k], otherwise Cython is using an intermediate buffer for buf=c[j], from which it will take buf[k], causing the slow-down. You should use this proper indexing plus the cdef declarations especified by @XavierCombelle.

You can check that this intermediate buffer is causing the slow-down by doing:

np.ndarray[DTYPE_t, ndim=1] buf

and then, inside the loop:

buf = c[j]
buf[k] = val_a + val_b

this declared buffer should give the same speed (or close) than:

c[j,k] = val_a + val_b
like image 113
Saullo G. P. Castro Avatar answered Sep 24 '22 01:09

Saullo G. P. Castro


I think you are missing

cdef int j
cdef int k

so your variable loop are python object not c ones

like image 39
Xavier Combelle Avatar answered Sep 27 '22 01:09

Xavier Combelle