¿Diferencia entre np.int, np.int_, int y np.int_t en cython?

7 minutos de lectura

¿Diferencia entre npint npint int y npint t en cython
colinfang

Estoy un poco luchando con tantos int tipos de datos en cython.

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

supongo int en Python puro es equivalente a np.int_entonces donde np.int ¿viene de? No puedo encontrar el documento de numpy? Además, ¿por qué np.int_ existe dado que ya tenemos int?

En cython, supongo 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 ¿C ª? entonces cdef long es idéntico a cdef np.int_?

¿Bajo qué circunstancias debo usar np.int_t en lugar de np.int? p.ej cdef np.int_t, ndarray[np.int_t]

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

Es un poco complicado porque los nombres tienen diferentes significados según el contexto.

int

  1. en pitón

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

    >>> int(10**50)
    100000000000000000000000000000000000000000000000000
    
  2. Sin embargo, cuando lo usa como dtype para una matriz NumPy se interpretará como np.int_ 1. Cual es no de precisión arbitraria, tendrá el mismo tamaño que el de 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:

    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 tipo c int. Es de precisión limitada (típicamente 32 bits). 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 fundición tipo:

    avalue = <int>(another_value)
    

    Y probablemente muchos más.

  4. En Cython pero como tipo Python. todavía puedes llamar int y obtendrá un “Python int” (de precisión arbitraria), o lo usará para isinstance o como dtype argumento a favor 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 así como. Sin embargo, no puede usarlo como identificador de tipo, excepto cuando lo usa en el cimportpaquete educativo. En ese caso, representa el tipo entero de Python.

cimport numpy as cnp

cpdef func(cnp.int obj):
    return obj

esto esperará obj ser un entero de Python no es 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ítelo siempre que sea posible. En código Python es equivalente a int y en código Cython también es equivalente a Pythons int pero si se usa como identificador de tipo, ¡probablemente lo confundirá a usted y a todos los que lean el código! Seguro que me confundió…

np.int_

En realidad solo tiene un significado: es un tipo pitón que representa un tipo escalar NumPy. Lo usas como 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

O lo usa para especificar el dtypepor 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 puede usarlo como argumento dtype. Pero puedes usarlo como tipo para cdef declaraciones:

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 usando el tipo de d sin el rastro t. ¡No puedes intercambiarlos en código Cython!

notas

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

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 Cython para np.bool_: cnp.npy_bool y bint pero ambos no se pueden usar para matrices NumPy actualmente. para escalares cnp.npy_bool solo será un entero sin signo mientras bint será un booleano. No estoy seguro de lo que está pasando allí…


1 Tomado de la Documentación de NumPy “Objetos de tipo de datos”

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_

  • ¡Muchas gracias por este resumen tan completo!

    – Axel

    21 de agosto de 2018 a las 7:39

¿Diferencia entre npint npint int y npint t en cython
Matti Lira

np.int_ es el tipo entero predeterminado (como se define en los documentos de NumPy), en un sistema de 64 bits esto sería un C long. np.intc es el predeterminado C int cualquiera int32 o int64. np.int es un alias para el incorporado int función

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

Los tipos de datos cython deben reflejar C tipos de datos, entonces cdef int a es un C int y así.

Como para np.int_t eso es el Cython tiempo de compilación equivalente de NumPy np.int_ tipo de datos, np.int64_t es el Cython Tiempo de compilación equivalente a np.int64

  • np.intc es prácticamente siempre de 32 bits. Nunca he visto un entorno C donde int es de 64 bits

    – Fred Foo

    18 de febrero de 2014 a las 12:39

  • ¿Puedo usar siempre np.int_t en lugar de np.int_ bajo cython cdefo viceversa?

    – colinfang

    18 de febrero de 2014 a las 13:21

  • No se puede usar al crear instancias de matrices numpy np.zeros(5, 5, dtype=np.int_t) arrojará un error donde como np.zeros(5, 5, dtype=np.int_) no lo haré Sin embargo, puede usarlo para declarar el tipo de matriz. np.ndarray[np.int_t] a = ... y dado que es una cosa de tiempo de compilación, recibirá advertencias tempranas de todos modos.

    – Matti Lyra

    18 de febrero de 2014 a las 13:49

  • Entonces, ¿puedo usar siempre np.int_ en lugar de np.int_t? ¿Sufro alguna pérdida de velocidad?

    – colinfang

    18 de febrero de 2014 a las 23:44

  • corrígeme si me equivoco, pero la pérdida de velocidad debería ser insignificante. La única diferencia sería que np.int_ puede (o no) tomar más de 4 bytes, mientras que np.int_t se garantiza 4 bytes.

    – Richizy

    20 de febrero de 2014 a las 7:33

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad