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...
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.
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.
Both are about 100x faster than numpy. Cupy is still convenient without much code change if your baseline code is in numpy.
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.
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())
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With