cython / numpy тип массива - PullRequest
       13

cython / numpy тип массива

5 голосов
/ 28 февраля 2012

Я пытаюсь построить матрицу типа Python int, 64-битное целое число со знаком.

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())

Он компилируется правильно, но когда я запускаю его, я получаю эту ошибку:

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

Я не могу работать с Python Long, но я не знаю, как правильно конвертировать в 64 int.

ОБНОВЛЕНИЕ

Окей. Я совершенно уверен, что я использовал Cython правильно. Код, который я написал, был для поиска minmax в игре capture go / atari go.

На данный момент наиболее вызываемыми являются следующие функции:

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

Я бы действительно подумал, что это будет шанс проявить себя на Cython. Чтобы решить захват 3х3, пройдите:

Python 2.7 дает согласованные 2,28 секунды, с Cython - согласованные 2,03 Оба были протестированы с модулем времени Python и на процессоре i7 с температурой ниже 60C °

Теперь вопрос для меня, собираюсь ли я перейти на Haskell или C ++ для этого проекта ...

1 Ответ

6 голосов
/ 28 февраля 2012

Тип Cython int совпадает с типом C int, т.е. обычно (но не обязательно) 32-разрядный.Вы должны объявить dtype в matrix33 как np.int64 и в do_stuf как его аналог C, 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())
...