web-dev-qa-db-ja.com

Cythonのnp.int、np.int_、int、およびnp.int_tの違いは?

私はcythonで非常に多くのintデータ型に苦労しています。

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

純粋なpythonのintは_np.int__と同等ですが、_np.int_はどこから来ますか?numpyからドキュメントを見つけることができませんか?また、すでにintがあるのに、なぜ_np.int__が存在するのですか?

Cythonでは、intは、_cdef int_または_ndarray[int]_として使用するとC型になり、int()として使用するとpythonキャスター?

_np.int__はCのlongと同等ですか?したがって、_cdef long_は_cdef np.int__と同じですか?

_np.int_t_ではなく_np.int_をどのような状況で使用する必要がありますか?例えば_cdef np.int_t_、_ndarray[np.int_t]_ ...

それらの型の誤った使用がコンパイルされたcythonコードのパフォーマンスにどのように影響するかを誰かが簡単に説明できますか?

33
colinfang

名前はコンテキストによって意味が異なるため、少し複雑です。

int

  1. Pythonで

    intは通常、単なるPython=型です。任意の精度です。つまり、考えられる整数をその中に格納できます(十分なメモリがある限り)。

    >>> int(10**50)
    100000000000000000000000000000000000000000000000000
    
  2. ただし、NumPy配列のdtypeとして使用すると、np.int_として解釈されます 1。これは、任意精度のではないであり、Cのlongと同じサイズになります。

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

    これは、次の2つが同等であることも意味します。

    np.array([1,2,3], dtype=int)
    np.array([1,2,3], dtype=np.int_)
    
  3. Cythonタイプ識別子には別の意味があります。ここでは、 c タイプ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)
    

    そしておそらくもっともっと。

  4. Cythonで、ただしPython typeです。intを呼び出すと、「Python int」(任意の精度)を取得するか、isinstanceまたはnp.arraydtype引数として。ここではコンテキストが重要であるため、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にも適用されます。ただし、cimportedパッケージで使用する場合を除いて、タイプ識別子として使用することはできません。その場合、それはPython整数型を表します。

cimport numpy as cnp

cpdef func(cnp.int obj):
    return obj

これはobjがNumPyタイプではないPython integer)であることを期待します

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

実際には、1つの意味しかありません。それは、スカラーNumPy型を表すPython型です。 Python 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が付いたtype-identifierが、実際にdtypeを使用して配列の型を表すことを示しています。 t。 Cythonコードでそれらを交換することはできません!

ノート

NumPyにはさらにいくつかの数値型があります。ここでは、NumPy dtypeとCython型識別子、およびCythonでも使用できるC型識別子を含むリストを含めます。ただし、基本的には NumPyのドキュメントCython 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ドキュメンテーション「データ型オブジェクト」 から取得

組み込み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_
30
MSeifert

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 aC intなどになります。

np.int_tは、NumPy np.int_データ型に相当するCythonコンパイル時間ですが、np.int64_tnp.int64に相当するCythonコンパイル時間です

7
Matti Lyra