【问题标题】:Numpy->Cython conversion: Compile error:Cannot convert 'npy_intp *' to Python objectNumpy->Cython 转换:编译错误:无法将 'npy_intp *' 转换为 Python 对象
【发布时间】:2012-03-16 04:23:06
【问题描述】:

我有以下要正确转换为 cython 的代码:

from numpy import *

## returns winning players or [] if undecided. 
def score(board):
    scores = []
    checked = zeros(board.shape)
    for i in xrange(len(board)):
        for j in xrange(len(board)):
            if checked[i,j] == 0 and board[i,j] !=0:
                ... do stuf

我尝试转换为 cython:

import numpy as np
cimport numpy as np

@cython.boundscheck(False)
@cython.wraparound(False)
@cython.nonecheck(False)

## returns winning players or [] if undecided. 
def score(np.ndarray[int, ndim=2] board):
    scores = []
    cdef np.ndarray[int, ndim = 2 ] checked
    checked = np.zeros(board.shape)
    for i in xrange(len(board)):
        for j in xrange(len(board)):
            if checked[i,j] == 0 and board[i,j] !=0:
                ... do stuf

但是当我编译时我得到:

$ python setup.py build_ext --inplace
running build_ext
cythoning newgox.pyx to newgox.c


## returns winning players or [] if undecided. 
def score(np.ndarray[int, ndim=2] board):
    scores = []
    cdef np.ndarray[int, ndim = 2 ] checked
    checked = np.zeros(board.shape)
                       ^
------------------------------------------------------------

newgox.pyx:58:28: Cannot convert 'npy_intp *' to Python object 
building 'newgox' extension

另外,我不确定这是在 cython 中使用列表的正确方法:

scores = []
if some_stuff_is_true:
    scores.append(some_integer)

编辑:

谢谢,代码现在可以编译,但是当我运行它时出现错误:

File "newgox.pyx", line 63, in newgox.score (newgox.c:1710)
    def score(np.ndarray[np.int, ndim=2] board):
ValueError: Buffer dtype mismatch, expected 'int object' but got 'long'

我将这两个选项捆绑在一起:

ctypedef np.int_t DTYPE_t
DTYPE = np.int

然后继续:

board = zeros((5,5), dtype = DTYPE)
def score(np.ndarray[DTYPE, ndim=2] board):

或者只是在两个声明中:

    ...  np.int ...

这会导致相同的错误,但带有签名:

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

感谢 bellamyj,但您建议的代码无法编译,

$ python setup.py build_ext --inplace
running build_ext
cythoning newgox.pyx to newgox.c
building 'newgox' extension
gcc-4.2 -fno-strict-aliasing -fno-common -dynamic -arch i386 -arch x86_64 -g -O2 -DNDEBUG -g -O3 -I/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 -c newgox.c -o   build/temp.macosx-10.6-intel-2.7/newgox.o

newgox.c:238:31: error: numpy/arrayobject.h: No such file or directory
newgox.c:239:31: error: numpy/ufuncobject.h: No such file or directory
newgox.c:356: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘__pyx_t_5numpy_int8_t’
newgox.c:365: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘__pyx_t_5numpy_int16_t’
newgox.c:374: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘__pyx_t_5numpy_int32_t’

它还会继续枚举所有其他类型。

然后是告诉我这个:

newgox.c:978: error: expected ‘)’ before ‘*’ token
newgox.c:979: error: expected ‘)’ before ‘*’ token
newgox.c:980: error: expected ‘)’ before ‘*’ token
newgox.c:983: error: expected declaration specifiers or ‘...’ before ‘PyArrayObject’
newgox.c:984: error: expected declaration specifiers or ‘...’ before ‘PyArrayObject’
newgox.c:985: error: expected ‘)’ before ‘*’ token
newgox.c:987: error: ‘__pyx_t_5numpy_int32_t’ undeclared here (not in a function)
newgox.c: In function ‘__pyx_pf_6newgox_7score’:
newgox.c:1638: error: ‘PyArrayObject’ undeclared (first use in this function)
newgox.c:1638: error: (Each undeclared identifier is reported only once
newgox.c:1638: error: for each function it appears in.)
newgox.c:1638: error: ‘__pyx_v_checked’ undeclared (first use in this function)
newgox.c:1659: error: ‘__pyx_t_5’ undeclared (first use in this function)
newgox.c:1721: error: expected expression before ‘)’ token
newgox.c:1723: error: expected expression before ‘)’ token
newgox.c:1747: error: expected expression before ‘)’ token
newgox.c:1766: error: expected expression before ‘)’ token
newgox.c:1813: error: expected expression before ‘)’ token
newgox.c:1846: error: expected expression before ‘)’ token
newgox.c:1846: error: too many arguments to function ‘__pyx_f_6newgox_check_life’
newgox.c:2009: error: expected expression before ‘)’ token
newgox.c:2009: warning: assignment makes pointer from integer without a cast
newgox.c:2012: error: expected expression before ‘)’ token
newgox.c:2032: error: expected expression before ‘)’ token
newgox.c: At top level:
newgox.c:2088: error: expected declaration specifiers or ‘...’ before ‘PyArrayObject’
newgox.c: In function ‘__pyx_f_6newgox_check_life’:
newgox.c:2124: error: ‘__pyx_v_board’ undeclared (first use in this function)
newgox.c:2160: error: ‘PyArrayObject’ undeclared (first use in this function)
newgox.c:2160: error: expected expression before ‘)’ token
newgox.c:2160: error: too many arguments to function ‘__pyx_f_6newgox_liberty’
newgox.c:2420: error: too many arguments to function ‘__pyx_f_6newgox_check_life’
newgox.c: At top level:
newgox.c:2583: error: expected declaration specifiers or ‘...’ before ‘PyArrayObject’
newgox.c: In function ‘__pyx_f_6newgox_liberty’:
newgox.c:2610: error: ‘__pyx_v_board’ undeclared (first use in this function)
newgox.c: At top level:
newgox.c:2859: error: expected ‘)’ before ‘*’ token
newgox.c: In function ‘__pyx_pf_5numpy_7ndarray___getbuffer__’:
newgox.c:2999: error: ‘PyArray_Descr’ undeclared (first use in this function)
newgox.c:2999: error: ‘__pyx_v_descr’ undeclared (first use in this function)
newgox.c:3062: error: ‘PyArrayObject’ undeclared (first use in this function)
newgox.c:3062: error: expected expression before ‘)’ token
newgox.c:3071: error: ‘npy_intp’ undeclared (first use in this function)
newgox.c:3114: error: expected expression before ‘)’ token
newgox.c:3114: error: ‘NPY_C_CONTIGUOUS’ undeclared (first use in this function)
newgox.c:3154: error: expected expression before ‘)’ token
newgox.c:3154: error: ‘NPY_F_CONTIGUOUS’ undeclared (first use in this function)
newgox.c:3184: error: expected expression before ‘)’ token
newgox.c:3184: warning: assignment makes pointer from integer without a cast
newgox.c:3240: error: expected expression before ‘)’ token
newgox.c:3240: error: subscripted value is neither array nor pointer
newgox.c:3249: error: expected expression before ‘)’ token
newgox.c:3249: error: subscripted value is neither array nor pointer
newgox.c:3262: error: expected expression before ‘)’ token
newgox.c:3271: error: expected expression before ‘)’ token
newgox.c:3291: error: expected expression before ‘)’ token

还有更多。

注意上面写着:

newgox.c:2160: error: too many arguments to function ‘__pyx_f_6newgox_liberty’
newgox.c:2420: error: too many arguments to function ‘__pyx_f_6newgox_check_life’

但我从 score/1 到 check_life 的电话是:

life, newly_checked = check_life(i,j,board,[])

它是这样接收的:

# helper functions of score/1
cdef check_life(int i, int j, np.ndarray[int, ndim=2] board, checked):
    ...
    return life, checked

最后,你用的“i4”是什么数据类型?

【问题讨论】:

    标签: python numpy scipy python-2.7 cython


    【解决方案1】:

    我认为 Cython 中的元组解包不像 Python 中那样有效。您必须使用(board.shape[0], board.shape[1]) 指定checked 的大小。

    您还需要指定checked 的数据类型。默认情况下,np.zeros 返回一个float64。您需要将其更改为 int32 以与声明的类型兼容。

    这是应该运行的修改版本。

    def score(np.ndarray[int, ndim=2] board):
    
        cdef np.ndarray[np.int32_t, ndim = 2] checked
        checked = np.zeros((board.shape[0], board.shape[1]), dtype='i4')
    
        for i in xrange(len(board)):
            for j in xrange(len(board)):
                if checked[i,j] == 0 and board[i,j] !=0:
                    ... do stuff
    

    要回答您问题的第二部分 - 是的,您可以附加到 Cython 函数中的列表。但是,据我了解,这涉及 Python 函数调用,因此它不会比 Python 中的相同操作快。

    更新 1:

    我相信这些错误是因为编译器找不到 NumPy 头文件。更新您的 setup.py 以包含这些文件的路径。路径应该由np.get_include()函数输出。

    import numpy as np
    from distutils.core import setup
    from distutils.extension import Extension
    from Cython.Distutils import build_ext
    
    setup(
          cmdclass={'build_ext': build_ext},
          ext_modules = [
                  Extension("new_gox",
                            ["new_gox.pyx"],
                            include_dirs=[np.get_include()])
                        ]
         )
    

    dtype i4 是一个 32 位整数。相当于np.int32

    我不确定“参数过多”错误是怎么回事。如果您在 Python 中调用该函数,则需要将其声明为 defcpdef。使用 cdef 声明的函数只能从 Cython 调用。这在 Cython 文档中描述为 here

    【讨论】:

      【解决方案2】:

      np.intp 等同于 (void *)

      像这样定义它的类型:

      ctypedef np.npy_intp SIZE_t              # Type for indices and counters
      

      来源:

      NPY_INTP == The enumeration value for a signed integer type which is the same size as a (void *) pointer. This is the type used by all arrays of indices.

      例如在 cython 中...

      头文件.h文件中的结构体:

      struct Cudamat_Struct1 {
          float * dataHost;
          float * dataDevice;
          int onDevice;
          int onHost;
          (void *) shape;
          int size;
          int isTrans; // 0 or 1
          int ownsData;
      
      };
      

      在 cython file.pxd 文件中:

      cdef extern from "file.h":
          cdef cppclass c_Cudamat_Struct "Cudamat_Struct":
              float *dataHost
              float *dataDevice
              bint onDevice
              bint onHost
              SIZE_t * shape
              int size
              bint isTrans
              bint ownsData
      

      终于在cython函数中:

      cdef pycublas_thrust_2d():
          cdef c_Cudamat_Struct1* mat = new c_Cudamat_Struct1()
      
          cdef int N = 10
      
          cdef np.ndarray[ndim=2, dtype=F32t] arrHost = np.ones((1,10),dtype=F32)
      
          cdef int size = 10
      
          cdef F32t[:,:] arrHost_ = arrHost
      
          cdef F32t * arrHostPtr = &arrHost[0,0]
      
          mat.dataHost = arrHostPtr
          mat.shape = arrHost.shape
          mat.size = size
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-06-05
        • 2020-04-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多