Cython / NumPy数组的类型是什么?

5
我正在尝试构建一个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位整数。 更新 好的。我相当确定我正确地使用了Cython。我编写的代码是用于在围棋/黑白棋游戏中进行极大极小搜索。
到目前为止,最常调用的函数是这些:
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大放异彩的机会。

要解决3x3的Capture Go问题:

Python 2.7花费了2.28秒,而使用Cython稳定在2.03秒。

两者都是用python时间模块测试的,在低于60°C的i7处理器上测试。

现在对我来说问题是,我是否要转而使用Haskell或C++来完成这个项目...

1个回答

6
Cython的int类型与C语言中的int类型相同,通常为32位(但不一定)。你应该将matrix33中的dtype声明为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())

谢谢,现在代码运行正确了。但是它的速度与我声明所有变量为long时一样快。我知道long对象不快,因为它不能溢出并且被处理方式不同(使用更多周期)。我想使用一个可以溢出且比Python类型long更快的int。 - Ihmahr
此外,相比解释型Python,加速只有不到10%,这让我怀疑我的类型可能还不太正确。 - Ihmahr
@user1020753:类型没问题。加速取决于您在函数中做什么。 - Fred Foo
@user1020753,你的函数大多数操作都使用Python数据类型,如列表、元组等。为了让Cython发挥更大的作用,需要重写代码以使用本地C数据类型。此外,如果你对函数进行类型注释,也可以提高运行速度。请参考http://docs.cython.org/src/quickstart/cythonize.html#typing-functions。 - joshayers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接