Подтвердить что ты не робот

Разница между np.int, np.int_, int и np.int_t в cython?

Я немного борюсь со многими типами данных int в cython.

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

Я предполагаю, что int в чистом питоне эквивалентен np.int_, тогда откуда происходит np.int? Я не могу найти документ из numpy? Кроме того, почему существует np.int_, если у нас уже есть int?

В cython, я думаю, int становится C-типом, когда используется как cdef int или ndarray[int], а когда используется как int(), он остается в качестве лидера python?

Является ли np.int_ эквивалентным long в C? поэтому cdef long является идентичным cdef np.int_?

В каких обстоятельствах следует использовать np.int_t вместо np.int? например cdef np.int_t, ndarray[np.int_t]...

Может кто-нибудь кратко объяснить, как неправильное использование этих типов повлияет на производительность скомпилированного кода на языке cython?

4b9b3361

Ответ 1

Это немного сложно, потому что имена имеют разные значения в зависимости от контекста.

int

  • В Python

    int обычно представляет собой просто тип Python, он произвольной точности, что означает, что вы можете хранить в нем любое мыслимое целое число (если у вас достаточно памяти).

    >>> int(10**50)
    100000000000000000000000000000000000000000000000000
    
  • Однако, когда вы используете его как 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_)
    
  • Как идентификатор типа Cython, он имеет другое значение, здесь он обозначает c type int. Он имеет ограниченную точность (обычно 32 бит). Вы можете использовать его как тип Cython, например, при определении переменных с помощью cdef:

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

    Как возвращаемое значение или значение аргумента для функций cdef или cpdef:

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

    Как "общий" для ndarray:

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

    Для литья типов:

    avalue = <int>(another_value)
    

    И, возможно, еще много.

  • В Cython, но как тип Python. Вы все равно можете вызвать int, и вы получите "Python int" (произвольной точности) или используйте его для isinstance или как аргумент dtype для np.array. Здесь очень важен контекст, поэтому преобразование в Python int отличается от преобразования в C int:

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

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 и идентификатор типа Cython, и идентификатор типа C, который также можно использовать в Cython. Но в основном это взято из документации NumPy и файл 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

На самом деле существуют типы Cython для np.bool_: cnp.npy_bool и bint, но оба они не могут использоваться для массивов NumPy в настоящее время. Для скаляров cnp.npy_bool будет просто целое число без знака, а bint будет логическим. Не уверен, что там происходит...


1 Взято из Документация NumPy "Объекты типа данных"

Встроенные типы Python

Несколько типов python эквивалентны соответствующему массиву массива при использовании для создания объекта 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_

Ответ 2

np.int_ - это целочисленный тип по умолчанию (как определено в документах NumPy), в 64-битной системе это будет C long. np.intc по умолчанию C int либо int32, либо int64. np.int является псевдонимом встроенной функции int

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

Типы данных cython должны отражать типы данных C, поэтому cdef int a - это C int и т.д.

Что касается np.int_t, то есть Cython эквивалент времени компиляции типа данных NumPy np.int_, np.int64_t является Cython эквивалентом времени компиляции np.int64