2012-02-26 43 views
11

Tôi đã đoạn mã sau đó là được propperly chuyển đổi sang cython:Numpy-> Cython chuyển đổi: Biên dịch lỗi: Không thể chuyển đổi 'npy_intp *' để đối tượng Python

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 

nỗ lực của tôi lúc chuyển đổi sang 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 

Nhưng khi tôi biên soạn tôi nhận được:

$ 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 

Ngoài ra, tôi không chắc chắn này là đúng cách để làm việc với lis ts trong cython:

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

EDIT:

Cảm ơn, mã ngay bây giờ biên dịch nhưng khi tôi chạy nó tôi nhận được lỗi:

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' 

tôi gắn liền với hai lựa chọn sau đây:

ctypedef np.int_t DTYPE_t 
DTYPE = np.int 

và sau đó tiếp tục đến:

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

hay chỉ là trong cả hai tuyên bố:

... np.int ... 

Điều này dẫn đến các lỗi tương tự, nhưng với chữ ký:

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

Cảm ơn bellamyj, nhưng mã đề nghị của bạn sẽ không biên dịch,

$ 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’ 

Và tiếp tục t o liệt kê tất cả các loại khác.

Sau đó là nói với tôi điều này:

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 

Và một số chi tiết.

Thông báo nó nói:

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’ 

Nhưng cuộc gọi của tôi từ điểm/1 tới check_life là:

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

Và nó nhận được như thế này:

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

Cuối cùng, những gì loại dữ liệu là "i4" mà bạn sử dụng?

Trả lời

14

Tôi không nghĩ rằng việc giải nén tuple hoạt động trong Cython giống như trong Python. Bạn phải chỉ định kích thước của checked bằng cách sử dụng (board.shape[0], board.shape[1]).

Bạn cũng cần chỉ định kiểu dữ liệu của checked. Theo mặc định np.zeros trả về một float64. Bạn cần thay đổi điều đó thành một số int32 để tương thích với loại được khai báo.

Đây là phiên bản đã sửa đổi sẽ chạy.

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 

Để trả lời phần thứ hai của câu hỏi - bạn có thể thêm vào danh sách trong các hàm Cython. Tuy nhiên, như tôi đã hiểu, điều này liên quan đến các cuộc gọi hàm Python, vì vậy nó sẽ không nhanh hơn các thao tác tương tự trong Python.

Cập nhật 1:

Tôi tin rằng những lỗi này vì trình biên dịch không thể tìm thấy các tập tin tiêu đề NumPy. Cập nhật setup.py của bạn để bao gồm đường dẫn đến các tệp đó. Đường dẫn phải được xuất bởi hàm 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 là số nguyên 32 bit. Nó tương đương với np.int32.

Tôi không chắc chắn điều gì xảy ra với lỗi 'quá nhiều đối số'. Nếu bạn đang gọi hàm đó từ bên trong Python, nó cần phải được khai báo là def hoặc cpdef. Các hàm được khai báo với cdef chỉ có thể được gọi từ Cython. Điều này được mô tả here trong tài liệu Cython.

1

np.intp là giống như (void *)

xác định loại của nó như thế này:

ctypedef np.npy_intp SIZE_t    # Type for indices and counters 

nguồn:

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.

Vì vậy, ví dụ như trong cython ...

Cấu trúc trong tệp tiêu đề.h tệp:

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

}; 

Trong file file.pxd cython:

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 

Cuối cùng trong chức năng 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 
Các vấn đề liên quan