Diferencia entre np.int, np.int, int, y np.int ¿t en cython?


Tengo problemas con tantos tipos de datos int en cython.

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

Supongo que int en python puro es equivalente a np.int_, entonces ¿de dónde viene np.int? No puedo encontrar el documento de numpy? Además, ¿por qué existe np.int_ dado que ya tenemos int?

En cython, supongo que int se convierte en un tipo C cuando se usa como cdef int o ndarray[int], y cuando se usa como int() se queda como el lanzador de python?

Es np.int_ equivalente a long en C? así que cdef long es el idéntica a cdef np.int_?

¿En qué circunstancias debo usar np.int_t en lugar de np.int? e. g.cdef np.int_t, ndarray[np.int_t] ...

¿Puede alguien explicar brevemente cómo el uso incorrecto de esos tipos afectaría el rendimiento del código compilado de cython?

Author: colinfang, 2014-02-18

2 answers

Es un poco complicado porque los nombres tienen diferentes significados dependiendo del contexto.

int

  1. En Python

    El int normalmente es solo un tipo Python, es de precisión arbitraria, lo que significa que puede almacenar cualquier entero concebible dentro de él (siempre y cuando tenga suficiente memoria).

    >>> int(10**50)
    100000000000000000000000000000000000000000000000000
    
  2. Sin embargo, cuando se utiliza como dtype para una matriz NumPy se interpretará como np.int_ 1. Que es no de precisión arbitraria, tendrá el mismo tamaño que C long:

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

    Eso también significa que los dos siguientes son equivalentes:{[55]]}

    np.array([1,2,3], dtype=int)
    np.array([1,2,3], dtype=np.int_)
    
  3. Como identificador de tipo Cython tiene otro significado, aquí representa el c tipo int. Es de precisión limitada (típicamente 32bits). Puede usarlo como tipo Cython, por ejemplo al definir variables con cdef:

    cdef int value = 100    # variable
    cdef int[:] arr = ...   # memoryview
    

    Como valor de retorno o valor de argumento para cdef o cpdef funciones:

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

    Como "genérico" para ndarray:

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

    Para el tipo de fundición:

    avalue = <int>(another_value)
    

    Y probablemente muchos más.

  4. En Cython pero como tipo Python. Todavía puedes llamar a int y obtendrás un "Python int" (de precisión arbitraria), o usarlo para isinstance o como argumento dtype para np.array. Aquí el contexto es importante, por lo que convertir a Python int es diferente de convertir a C int:

    cdef object val = int(10)  # Python int
    cdef int val = <int>(10)   # C int
    

np.int

En realidad esto es muy fácil. Es solo un alias para int:

>>> int is np.int
True

Así que todo lo de arriba se aplica a np.int también. Sin embargo, no se puede utilizar como un identificador de tipo, excepto cuando se utiliza en el paquete ed cimport. En ese caso representa el tipo entero de Python.

cimport numpy as cnp

cpdef func(cnp.int obj):
    return obj

Esto esperará que obj sea un entero Python no un tipo NumPy :

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

Mi consejo con respecto a np.int: Evítalo siempre que sea posible. En código Python es equivalente a int y en Cython código también es equivalente a Pythons int pero si se usa como identificador de tipo, probablemente te confundirá a ti y a todos los que lean el código. Ciertamente me confundió...

np.int_

En realidad solo tiene un significado: Es un tipo Python que representa un tipo NumPy escalar. Lo usas como Pitones int: {[55]]}

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

O lo usa para especificar el dtype, por ejemplo con np.array:

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

Pero no puede usarlo como identificador de tipo en Cython.

cnp.int_t

Es la versión del identificador de tipo para np.int_. Eso significa que no puedes usarlo como argumento dtype. Pero puede usarlo como tipo para las declaraciones cdef:

cimport numpy as cnp
import numpy as np

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

Este ejemplo (con suerte) muestra que el identificador de tipo con el final _t en realidad representa el tipo de una matriz que utiliza el dtype sin el final t. ¡No puedes intercambiarlos en código Cython!

Notas

Hay varios tipos numéricos en NumPy incluiré una lista que contiene el dtype NumPy y el identificador de tipo Cython y el identificador de tipo C que también se podría usar en Cython aquí. Pero básicamente está tomado de la documentación de NumPy y el archivo Cython NumPy pxd :

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

En realidad hay tipos de citones para np.bool_: cnp.npy_bool y bint pero ambos no se pueden usar para matrices NumPy actualmente. Para los escalares cnp.npy_bool solo será un entero sin signo mientras que bint será un booleano. No estoy seguro qué está pasando ahí...


1 Tomado de la documentación de NumPy"Data type objects"

Tipos de Python integrados

Varios tipos de python son equivalentes a un escalar de matriz correspondiente cuando se usan para generar un objeto dtype:

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_
 15
Author: MSeifert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-26 00:57:07

np.int_ es el tipo entero predeterminado ( como se define en NumPy docs), en un sistema de 64 bits esto sería un C long. np.intc es el valor predeterminado C int ya sea int32 o int64. {[7] } es un alias de la función incorporada int

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

Los tipos de datos de cython deben reflejar C tipos de datos, por lo que cdef int a es un C int y así sucesivamente.

En cuanto a np.int_t que es el Cython equivalente en tiempo de compilación del tipo de datos NumPy np.int_, np.int64_t es el Cython equivalente en tiempo de compilación de np.int64

 7
Author: Matti Lyra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-18 12:35:54