【问题标题】:cython / numpy type of an arraycython / numpy 类型的数组
【发布时间】:2012-03-17 21:16:52
【问题描述】:

我正在尝试构造一个 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。我写的代码是在抓包游戏/雅达利围棋中进行最小最大搜索。

到目前为止,调用次数最多的函数是:

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 捕获问题:

Python 2.7 执行一致的 2.28 秒,使用 cython 执行一致的 2.03 两者均使用 python 时间模块和低于 60C° 的 i7 处理器进行了测试

现在我的问题是我是否要为这个项目切换到 Haskell 或 C++...

【问题讨论】:

    标签: python types numpy python-2.7 cython


    【解决方案1】:

    Cython 的 int 类型与 C int 相同,即通常(但不一定)32 位。您应该将matrix33 中的dtype 声明为np.int64,并将do_stuf 中的np.int64_t 声明为C 对应项:

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

    【讨论】:

    • 谢谢,代码现在运行正确。但是,它的运行速度与我声明所有内容时一样快。我知道长对象并不快,因为它不能溢出并且被区别对待(使用更多周期)。我想使用一个可以溢出的int,它比python类型long快。
    • 另外,解释型 python 的速度提升不到 10%,这让我怀疑我没有完全正确的类型...
    • @user1020753:类型正确。加速取决于您在函数中执行的操作。
    • @user1020753 您的函数使用 Python 数据类型(列表、元组等)进行大部分操作。要使 Cython 产生较大的影响,需要对其进行重写以使用本机 C 数据类型。此外,如果您键入函数,它可能会加快速度。见docs.cython.org/src/quickstart/cythonize.html#typing-functions
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-18
    • 1970-01-01
    相关资源
    最近更新 更多