cython中np.int,np.int_,int和np.int_t之间的区别?

时间:2014-02-18 11:11:51

标签: python c numpy cython

我对cython中的这么多int数据类型感到有点挣扎。

np.int, np.int_, np.int_t, int

我认为纯python中的int等同于np.int_,那么np.int来自哪里?我从numpy找不到文件?另外,为什么np.int_存在,因为我们已经有int

在cython中,我猜int在用作cdef intndarray[int]时会变成C类型,当用作int()时,它会像蟒蛇一样停留吗?

C np.int_相当于long吗?所以cdef longcdef np.int_相同?

在什么情况下我应该使用np.int_t代替np.int?例如cdef np.int_tndarray[np.int_t] ...

有人可以简单解释这些类型的错误使用会如何影响已编译的cython代码的性能吗?

2 个答案:

答案 0 :(得分:28)

这有点复杂,因为名称根据上下文有不同的含义。

int

  1. 在Python中

    int通常只是一个Python类型,它具有任意精度,这意味着你可以在其中存储任何可以想象的整数(只要你有足够的内存)。

    >>> int(10**50)
    100000000000000000000000000000000000000000000000000
    
  2. 但是,当您将dtype用作NumPy数组时,它将被解释为np.int_ 1 。哪个是的任意精度,它将与C的long具有相同的大小:

    >>> np.array(10**50, dtype=int)
    OverflowError: Python int too large to convert to C long
    

    这也意味着以下两个是等价的:

    np.array([1,2,3], dtype=int)
    np.array([1,2,3], dtype=np.int_)
    
  3. 作为Cython类型标识符,它有另一种含义,这里它代表类型int。它的精度有限(通常为32位)。您可以将其用作Cython类型,例如在使用cdef

    定义变量时
    cdef int value = 100    # variable
    cdef int[:] arr = ...   # memoryview
    

    作为cdefcpdef函数的返回值或参数值:

    cdef int my_function(int argument1, int argument2):
        # ...
    

    ndarray的“通用”:

    cimport numpy as cnp
    cdef cnp.ndarray[int, ndim=1] val = ...
    

    对于类型转换:

    avalue = <int>(another_value)
    

    可能还有更多。

  4. 在Cython中,但作为Python类型。您仍然可以调用int并获得“Python int”(任意精度),或者将其用于isinstancedtype作为np.array的参数。这里的上下文很重要,因此转换为Python int与转换为C int:

    不同
    cdef object val = int(10)  # Python int
    cdef int val = <int>(10)   # C int
    
  5. np.int

    实际上这很容易。它只是int的别名:

    >>> int is np.int
    True
    

    所以上面的所有内容也适用于np.int。但是,除非在cimport ed包上使用它,否则不能将其用作类型标识符。在这种情况下,它表示Python整数类型。

    cimport numpy as cnp
    
    cpdef func(cnp.int obj):
        return obj
    

    这将使obj成为Python整数而不是NumPy类型

    >>> func(np.int_(10))
    TypeError: Argument 'obj' has incorrect type (expected int, got numpy.int32)
    >>> func(10)
    10
    

    我对np.int的建议:尽可能避免使用它。在Python代码中,它等同于int,在Cython代码中它也等同于Pythons int,但如果用作类型标识符,它可能会使您和阅读代码的每个人感到困惑!这当然让我很困惑......

    np.int_

    实际上它只有一个含义:它是一个 Python类型,代表一个标量NumPy类型。你像Pythons int一样使用它:

    >>> np.int_(10)        # looks like a normal Python integer
    10
    >>> type(np.int_(10))  # but isn't (output may vary depending on your system!)
    numpy.int32
    

    或者您使用它来指定dtype,例如使用np.array

    >>> np.array([1,2,3], dtype=np.int_)
    array([1, 2, 3])
    

    但你不能在Cython中将它用作类型标识符。

    cnp.int_t

    这是np.int_的类型标识符版本。这意味着你不能将它用作dtype参数。但您可以将其用作cdef声明的类型:

    cimport numpy as cnp
    import numpy as np
    
    cdef cnp.int_t[:] arr = np.array([1,2,3], dtype=np.int_)
         |---TYPE---|                         |---DTYPE---|
    

    此示例(希望如此)显示带有尾随_t的类型标识符实际上表示使用 dtype 而没有尾随t的数组类型。你不能用Cython代码交换它们!

    注释

    NumPy中还有几种数字类型我将包含一个包含NumPy dtype和Cython类型标识符的列表以及也可以在Cython中使用的C类型标识符。但它基本上取自the NumPy documentationCython NumPy pxd file

    NumPy dtype          Numpy Cython type         C Cython type identifier
    
    np.bool_             None                      None
    np.int_              cnp.int_t                 long
    np.intc              None                      int       
    np.intp              cnp.intp_t                ssize_t
    np.int8              cnp.int8_t                signed char
    np.int16             cnp.int16_t               signed short
    np.int32             cnp.int32_t               signed int
    np.int64             cnp.int64_t               signed long long
    np.uint8             cnp.uint8_t               unsigned char
    np.uint16            cnp.uint16_t              unsigned short
    np.uint32            cnp.uint32_t              unsigned int
    np.uint64            cnp.uint64_t              unsigned long
    np.float_            cnp.float64_t             double
    np.float32           cnp.float32_t             float
    np.float64           cnp.float64_t             double
    np.complex_          cnp.complex128_t          double complex
    np.complex64         cnp.complex64_t           float complex
    np.complex128        cnp.complex128_t          double complex
    

    实际上np.bool_cnp.npy_boolbint都有Cython类型,但它们目前都不能用于NumPy数组。对于标量cnp.npy_bool将只是一个无符号整数,而bint将是一个布尔值。不知道那里发生了什么......

    1 取自NumPy documentation "Data type objects"

      

    内置Python类型

         

    当用于生成dtype对象时,有几种python类型等效于相应的数组标量:

    int           np.int_
    bool          np.bool_
    float         np.float_
    complex       np.cfloat
    bytes         np.bytes_
    str           np.bytes_ (Python2) or np.unicode_ (Python3)
    unicode       np.unicode_
    buffer        np.void
    (all others)  np.object_
    

答案 1 :(得分:7)

np.int_是默认的整数类型(as defined in the NumPy docs),在64位系统上,这将是C longnp.intcC intint32的默认int64np.int是内置int函数

的别名
>>> np.int(2.4)
2
>>> np.int is int  # object id equality
True

cython数据类型应该反映C个数据类型,因此cdef int aC int,依此类推。

至于np.int_t,即Cython编译时间等效于NumPy np.int_数据类型,np.int64_t是等效于{{1}的Cython编译时间}}