Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cython / numpy type of an array

I am trying to construct a matrix of python type int, a 64bit signed integer.

cdef matrix33():
    return np.zeros((3,3),dtype=int)

cdef do_stuf(np.ndarray[int, ndim=2] matrix):
    ...
    return some_value

def start():
    print do_stuf(matrix33())

It compiles right, but when I run it I keep getting this error:

ValueError: Buffer dtype mismatch, expected 'int' but got 'long'

I can not work with python long's, but I don't know how to properly convert to a 64 int.

UPDATE

Okey. I am quite sure that I used Cython correctly. The code that I wrote was for an minmax search in the game of capture go / atari go.

By far the most called functions are these:

cdef isThere_greedy_move(np.ndarray[np.int64_t, ndim=2]board, int player):
    cdef int i, j
    for i in xrange(len(board)):
        for j in xrange(len(board)):
            if board[i,j] == 0:
                board[i,j] = player
                if player in score(board):
                    board[i,j] = 0
                    return True
                board[i,j] = 0
    return False


# main function of the scoring system.
# returns list of players that eat a stone
cdef score(np.ndarray[np.int64_t, ndim=2] board):
    scores = []
    cdef int i,j
    cdef np.ndarray[np.int64_t, ndim = 2] checked
    checked = np.zeros((board.shape[0], board.shape[1]), dtype = int)
    for i in xrange(len(board)):
        for j in xrange(len(board)):
            if checked[i,j] == 0 and board[i,j] !=0:
                life, newly_checked = check_life(i,j,board,[])
                if not life:
                    if -board[i,j] not in scores:
                        scores.append(-board[i,j])
                        if len(scores) == 2:
                            return scores
                checked = update_checked(checked, newly_checked)
    return scores

# helper functions of score/1
cdef check_life(int i, int j, np.ndarray[np.int64_t, ndim=2] board, checked):
    checked.append((i,j))
    if liberty(i,j,board):
        return True, checked
    for pos in [[1,0],[0,1],[-1,0],[0,-1]]:
        pos = np.array([i,j]) + np.array(pos)
        if check_index(pos[0],pos[1],len(board)) and board[pos[0],pos[1]] == board[i,j] and (pos[0],pos[1]) not in checked:
            life, newly_checked = check_life(pos[0],pos[1],board,checked)
            if life:
                checked = checked + newly_checked             
                return life, checked
    return False, []    # [] is a dummy.

cdef liberty(int i,int j, np.ndarray[np.int64_t, ndim=2] board):
    for pos in [np.array([1,0]),np.array([0,1]),np.array([-1,0]),np.array([0,-1])]:
        pos = np.array([i,j]) - pos
        if check_index(pos[0],pos[1],len(board)) and board[pos[0],pos[1]] == 0:
            return True
    return False

I would really have thought that this would be a chance to shine for cython. To solve 3x3 capture go:

Python 2.7 does a consistent 2.28 seconds, with cython it is a consistent 2.03 Both were tested with the python time module and on an i7 processor of less than 60C°

Now the question for me is if I am going to switch to Haskell or C++ for this project...

like image 855
Ihmahr Avatar asked Feb 28 '12 11:02

Ihmahr


People also ask

Can you use NumPy with Cython?

You can use NumPy from Cython exactly the same as in regular Python, but by doing so you are losing potentially high speedups because Cython has support for fast access to NumPy arrays.

Is Numba better than Cython?

The Takeaway. So numba is 1000 times faster than a pure python implementation, and only marginally slower than nearly identical cython code. There are some caveats here: first of all, I have years of experience with cython, and only an hour's experience with numba.

Is CUPY faster than NumPy?

Both are about 100x faster than numpy. Cupy is still convenient without much code change if your baseline code is in numpy.

How much faster is Cython?

When Cython encounteres Python code it can't translate completely into C, it transforms that code into a series of C calls to Python's internals. This amounts to taking Python's interpreter out of the execution loop, which gives code a modest 15 to 20 percent speedup by default.


1 Answers

Cython's int type is the same as a C int, i.e. usually (but not necessarily) 32-bit. You should declare the dtype in matrix33 as np.int64 and in do_stuf as its C counterpart, np.int64_t:

cimport numpy as np
import numpy as np

cdef do_stuff(np.ndarray[np.int64_t, ndim=2] matrix):
    pass

cdef matrix33():
    return np.zeros((3,3), dtype=int)

def start():
    print do_stuff(matrix33())
like image 106
Fred Foo Avatar answered Sep 30 '22 12:09

Fred Foo