Unterschied zwischen np.int, np.int_, int und np.int_t in Cython?

Lesezeit: 8 Minuten

colinfangs Benutzeravatar
Colinfang

Ich habe mit so vielen etwas zu kämpfen int Datentypen in cython.

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

ich vermute int in reinem Python entspricht np.int_wo dann np.int komme aus? Ich kann das Dokument von numpy nicht finden? Auch warum np.int_ existieren, da wir bereits haben int?

In Cython, schätze ich int wird ein C-Typ, wenn es als verwendet wird cdef int oder ndarray[int]und wenn verwendet als int() es bleibt beim python caster?

Ist np.int_ gleichwertig long in C? Also cdef long ist identisch mit cdef np.int_?

Unter welchen Umständen sollte ich verwenden np.int_t Anstatt von np.int? z.B cdef np.int_t, ndarray[np.int_t]

Kann jemand kurz erklären, wie sich die falsche Verwendung dieser Typen auf die Leistung von kompiliertem Cython-Code auswirken würde?

Es ist ein bisschen kompliziert, weil die Namen je nach Kontext unterschiedliche Bedeutungen haben.

int

  1. Bei Python

    Das int ist normalerweise nur ein Python-Typ, es ist von beliebiger Genauigkeit, was bedeutet, dass Sie jede denkbare ganze Zahl darin speichern können (solange Sie genug Speicher haben).

    >>> int(10**50)
    100000000000000000000000000000000000000000000000000
    
  2. Allerdings, wenn Sie es als verwenden dtype für ein NumPy-Array wird es interpretiert als np.int_ 1. Welches ist nicht von beliebiger Genauigkeit, hat es die gleiche Größe wie C’s long:

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

    Das bedeutet auch, dass die folgenden beiden äquivalent sind:

    np.array([1,2,3], dtype=int)
    np.array([1,2,3], dtype=np.int_)
    
  3. Als Cython-Typ-Bezeichner hat es eine andere Bedeutung, hier steht es für den c-Typ int. Es ist von begrenzter Genauigkeit (normalerweise 32 Bit). Sie können es als Cython-Typ verwenden, zum Beispiel beim Definieren von Variablen mit cdef:

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

    Als Rückgabewert oder Argumentwert für cdef oder cpdef Funktionen:

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

    Als “generisch” für ndarray:

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

    Für Type-Casting:

    avalue = <int>(another_value)
    

    Und wahrscheinlich noch viele mehr.

  4. In Cython, aber als Python-Typ. Sie können immer noch anrufen int und Sie erhalten ein “Python int” (mit beliebiger Genauigkeit) oder verwenden es für isinstance oder als dtype Argument für np.array. Hier ist der Kontext wichtig, also in Python umwandeln int unterscheidet sich von der Konvertierung in ein C int:

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

np.int

Eigentlich ist das ganz einfach. Es ist nur ein Alias ​​für int:

>>> int is np.int
True

Also trifft alles von oben zu np.int auch. Sie können es jedoch nicht als Typkennung verwenden, außer wenn Sie es auf der verwenden cimportEd-Paket. In diesem Fall repräsentiert es den Python-Integer-Typ.

cimport numpy as cnp

cpdef func(cnp.int obj):
    return obj

Dies wird erwartet obj eine Python-Ganzzahl sein kein NumPy-Typ:

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

Mein Tipp bzgl np.int: Vermeiden Sie es, wann immer möglich. Im Python-Code ist es äquivalent zu int und im Cython-Code entspricht es auch Pythons int aber wenn es als Typkennung verwendet wird, wird es Sie und jeden, der den Code liest, wahrscheinlich verwirren! Es hat mich natürlich verwirrt…

np.int_

Eigentlich hat es nur eine Bedeutung: Es ist ein Python-Typ das einen skalaren NumPy-Typ darstellt. Sie verwenden es wie 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

Oder Sie verwenden es, um die zu spezifizieren dtypezum Beispiel mit np.array:

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

Sie können es jedoch nicht als Typkennung in Cython verwenden.

cnp.int_t

Es ist die Typkennungsversion für np.int_. Das heißt, Sie können es nicht als dtype-Argument verwenden. Aber Sie können es als Typ für verwenden cdef Erklärungen:

cimport numpy as cnp
import numpy as np

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

Dieses Beispiel zeigt (hoffentlich) dass die Typkennung mit dem Trailing _t stellt tatsächlich den Typ eines Arrays dar, das die verwendet dtyp ohne Nachlauf t. Sie können sie nicht im Cython-Code austauschen!

Anmerkungen

Es gibt mehrere weitere numerische Typen in NumPy. Ich füge eine Liste mit dem NumPy-Dtype und der Cython-Typkennung und der C-Typkennung hinzu, die hier auch in Cython verwendet werden könnten. Aber es ist im Grunde übernommen die NumPy-Dokumentation und die Cython NumPy pxd Datei:

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

Eigentlich gibt es Cython-Typen für np.bool_: cnp.npy_bool und bint aber beide können derzeit nicht für NumPy-Arrays verwendet werden. Für Skalare cnp.npy_bool wird nur eine vorzeichenlose ganze Zahl sein, während bint wird ein boolescher Wert sein. Bin mir nicht sicher was da los ist…


1 Entnommen aus der NumPy-Dokumentation “Datentypobjekte”

Eingebaute Python-Typen

Mehrere Python-Typen entsprechen einem entsprechenden Array-Skalar, wenn sie zum Generieren eines dtype-Objekts verwendet werden:

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_

  • Vielen Dank für diese sehr ausführliche Übersicht!

    – Axel

    21. August 2018 um 7:39 Uhr

  • Wie wäre es mit np.integer?

    – Heberto Mayorquin

    8. Juni um 16:13 Uhr

  • @HebertoMayorquin ist eine abstrakte Basisklasse, die zum Überprüfen vorhanden ist (mit isinstance oder issubclass), wenn Sie einen ganzzahligen dtype haben (vergleichbar mit collections.abc.Hashable und ähnliches). Da es sich nicht um einen “echten” dtype handelt und (soweit ich weiß) nicht speziell in Cython implementiert ist, ist es für diese Frage nicht wirklich relevant. Aber zögern Sie nicht, eine neue Frage zu stellen, wenn Sie etwas Bestimmtes wissen möchten.

    – MSeifert

    8. Juni um 16:37 Uhr


  • @MSeifert danke, das war es. Ich schätze, dass die Tatsache, dass die dtypes ähnliche Namen wie die abstrakten Klassen für die Objekte haben, mich verwirrt hat. Dies kam von hier: stackoverflow.com/questions/72549583/…

    – Heberto Mayorquin

    8. Juni um 16:59 Uhr

Benutzeravatar von Matti Lyra
Matti Lyra

np.int_ ist der standardmäßige ganzzahlige Typ (wie in den NumPy-Dokumenten definiert), auf einem 64-Bit-System wäre dies a C long. np.intc ist die Vorgabe C int entweder int32 oder int64. np.int ist ein Alias ​​für die eingebaute int Funktion

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

Die Cython-Datentypen sollten widerspiegeln C Datentypen, also cdef int a ist ein C int usw.

Wie für np.int_t das ist die Cython Kompilierzeitäquivalent von NumPy np.int_ Datentyp, np.int64_t ist der Cython Kompilierzeitäquivalent von np.int64

  • np.intc ist praktisch immer 32 Bit. Ich habe noch nie eine C-Umgebung gesehen, in der int ist 64 Bit.

    – Fred Foo

    18. Februar 2014 um 12:39 Uhr

  • Kann ich immer verwenden np.int_t Anstatt von np.int_ unter Cython cdefoder umgekehrt?

    – Colinfang

    18. Februar 2014 um 13:21 Uhr

  • Sie können nicht verwenden, wenn Sie numpy-Arrays instanziieren np.zeros(5, 5, dtype=np.int_t) wird einen Fehler ausgeben, wo als np.zeros(5, 5, dtype=np.int_) Gewohnheit. Sie können es jedoch verwenden, um den Typ des Arrays zu deklarieren np.ndarray[np.int_t] a = ... und da es sich um eine Kompilierzeit handelt, erhalten Sie sowieso Frühwarnungen.

    – Matti Lyra

    18. Februar 2014 um 13:49 Uhr

  • Dann kann ich immer verwenden np.int_ Anstatt von np.int_t? Habe ich einen Geschwindigkeitsverlust?

    – Colinfang

    18. Februar 2014 um 23:44 Uhr

  • Korrigieren Sie mich, wenn ich falsch liege, aber der Geschwindigkeitsverlust sollte vernachlässigbar sein. Der einzige Unterschied wäre der np.int_ kann (oder auch nicht) mehr als 4 Bytes benötigen, während np.int_t garantiert 4 Bytes.

    – reich

    20. Februar 2014 um 7:33 Uhr

Dies ist eine Klärung des Unterschieds zwischen int und np.int_t im Cython-Code, die nicht gleich sind:

np.int_t Karten zu long und nicht zu int im Cython-Code.

Das bedeutet:

  • Unter 64-Bit-Windows (dh mit MSVC kompiliert) int ist aber auch 4 bytes long (und somit np.int_t).
  • Unter 64-Bit-Linux (dh mit gcc kompiliert) int ist aber 4 Bytes long (und somit np.int_t) ist 8 Byte!

Ein np.int-numpy-array würde zuordnen np.int_t[:]-Speicheransicht in Cython, was richtig ist, weil der folgende Code:

import numpy as np

a = np.zeros(1, np.int_)  # or np.zeros(1, np.int)
print(a.itemsize)

ergäbe 4 (Größe von long in Bytes unter Windows) unter Windows und 8 auf Linux.

Oft ist es sinnvoll, die Größe der Werte genau anzugeben, zB durch using np.int32 und np.int64 was zuordnen würde np.int32_t und np.int64_t in Cython und haben auf allen Plattformen die gleiche Größe.

1411400cookie-checkUnterschied zwischen np.int, np.int_, int und np.int_t in Cython?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy