How to declare 2D c-arrays dynamically in Cython

I need to work hard using numpy 2D arrays of various sizes, and I would like to offload these calculations in cython. The idea is that my numpy 2D arrays will be passed from python to cython, where it will be converted to a c-array or memory representation and used in a cascade of other level c functions to perform the calculations.

After some profiling, I ruled out the use of numpy arrays in cython due to some serious python overhead. Using memory representations was much faster and fairly easy to use, but I suspect that I can compress even more acceleration from using c-arrays.

Here is my question: how can I declare a 2D-c array in a tseton without predetermining its sizes with the set values? For example, I can create a c-array from numpy as follows:

narr = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]], dtype=np.dtype("i"))

cdef int c_arr[3][4]:
for i in range(3):
    for j in range(4):
        c_arr[i][j] = narr[i][j]

and then pass it to the function:

cdef void somefunction(int c_Arr[3][4]):
    ...

But this means that I have a fixed array value, which in my case will be useless. So I tried something like this:

narr = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]], dtype=np.dtype("i"))

cdef int a = np.shape(narr)[0]
cdef int b = np.shape(narr)[1]

cdef int c_arr[a][b]:               # INCORRECT - EXAMPLE ONLY

for i in range(a):
    for j in range(b):
        c_arr[i][j] = narr[i][j]

with the intention of passing it to such a function:

cdef void somefunction(int a, int b, int c_Arr[a][b]):
    ...

But this will not work, and the compilation failed with the error "Not allowed in constant expression." I suspect I need to do this with malloc / free somehow? I examined this problem ( How to declare a 2D list in Cython ), but it does not give an answer to my problem.

UPDATE:

, , c-, , cython , cython:

# cython: boundscheck=False

@Veedrac !

+4
2

:

with cython.boundscheck(False):
    thesum += x_view[i,j]

.


C, :

import numpy as numpy
from numpy import int32
from numpy cimport int32_t

numpy_array = numpy.array([[]], dtype=int32)

cdef:
    int32_t[:, :] cython_view = numpy_array
    int32_t *c_integers_array = &cython_view[0, 0]
    int32_t[4] *c_2d_array = <int32_t[4] *>c_integers_array

Numpy. , . , .

+7

, @Veedrac ( !) script, , c- Cython. , , .

cython script, "" numpy c-, c-:

# cython: boundscheck=False

cimport cython
import numpy as np
cimport numpy as np

from numpy import int32
from numpy cimport int32_t


#Generate numpy array:
narr = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]], dtype=np.dtype("i"))

cdef int a = np.shape(narr)[0]
cdef int b = np.shape(narr)[1]
cdef int i, j

testsum = np.sum(narr)
print "Test summation: np.sum(narr) =", testsum

#Generate the memory view:
cdef int [:,:] x_view = narr

#Generate the 2D c-array and its pointer:
cdef:
    int32_t[:, :] cython_view = narr
    int32_t *c_integers_array = &cython_view[0, 0]
    int32_t[4] *c_arr = <int32_t[4] *>c_integers_array


def test1():

    speed_test_mview(x_view)  

def test2():

    speed_test_carray(&c_arr[0][0], a, b)


cdef int speed_test_mview(int[:,:] x_view):

    cdef int n, i, j, thesum

    # Define the view:
    for n in range(10000):
    thesum = 0
    for i in range(a):
        for j in range(b):
            thesum += x_view[i, j]        


cdef int speed_test_carray(int32_t *c_Arr, int a, int b):

    cdef int n, i, j, thesum
    for n in range(10000):
    thesum = 0
    for i in range(a):
        for j in range(b):
            thesum += c_Arr[(i*b)+j]

, ipython, :

import testlib as t
Test summation: np.sum(narr) = 136

%timeit t.test1()
10000000 loops, best of 3: 46.3 ns per loop

%timeit t.test2()
10000000 loops, best of 3: 46 ns per loop

Oh - numpy 125 ( ).

+1

All Articles