Cython: 缓冲区类型不匹配,期望为 'int' 但实际得到的是 'long'。

21

我在尝试将这个整数的memoryview传递给这个(相当琐碎的)函数时遇到了问题。Python 给了我这个错误:

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

有人能帮我理解一下发生了什么吗?在stackoverflow上搜索,似乎与Python解释类型的方式以及C解释类型的方式有关。

%%cython
def myfunction(int [:] y):
    pass

# Python code
import numpy as np
y = np.array([0, 0, 1, 1])
myfunction(y)

这会产生上面提到的 ValueError 错误。

编辑:我还发现了一些其他问题。

为了澄清,如果我按照以下方式声明y,则仍然会出现此错误:

y = np.array([0, 0, 1, 1], dtype='int')
y = np.array([0, 0, 1, 1], dtype=np.int)
y = np.array([0, 0, 1, 1], dtype=np.int64)

然而,如果我使用以下方式声明y,它将起作用:

y = np.array([0, 0, 1, 1], dtype=np.int32)

有人可以提供为什么会出现这种情况的建议吗?在不同的计算机上使用 np.int32 会起作用吗?(我使用的是MacBook Pro Retina,2013年版。)

3个回答

18
您正在使用Cython的int类型,它就是C中的int。我认为在Mac(或大多数架构)上,它是32位int。请参见维基百科英特尔一个int的大小是否取决于编译器和/或处理器?

另一方面,long意味着int64。 dtype ='int'dtype =np.intnp.int64相当。

我认为您只需明确将其定义为numpy类型之一:

cimport numpy as np
import numpy as np
cdef myfunction(np.ndarray[np.int64_t, ndim=1] y):
     #do something
     pass

这样阅读起来更加清晰,后面也不会有任何混淆。

编辑

使用更新的memoryviews语法,如下所示:

cdef myfunction(double[:] y):
    #do something with y
    pass

谢谢您的见解。在每台计算机上都可以使用np.int64_t吗?(我知道我之前问过是否在所有计算机上都可以使用dtype=np.int32,但这个选项是在Python代码中的。我想知道您提供的np.int64_t选项是否适用于所有计算机,因为它是Cython代码。) - hlin117
1
我认为是这样。因为它在函数声明中,只要我们将np.int64数组传递给它,它就可以很好地完成任务。np.int64_t在内部如何转换为C类型,这是numpy的问题,而不是我们的问题(我相信它已经得到了解决,:P)。抱歉,这不是一个明确的答案,但我经常在教程和其他人的代码中看到这种用法。 - CT Zhu
2
我相信现在更倾向于使用memoryview语法而不是声明为numpy数组(它的适用范围更广,速度基本相同)。但关于np.int64的观点是正确的。 - DavidW

1

我也遇到了同样的问题。受Yibo的回答启发,我使用了.astype(int)方法,解决了这个问题。


1
我按照错误信息提示的做法进行了操作:将memoryview的基本类型从int更改为long,似乎起作用了。
%%cython
def fun(long[:] x):
    return x[0]

y=np.array([1,2,3],dtype=int)
fun(y)    # returns 1

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