Cpython vs cython vs numpy Array Leistung

Ich mache einige Leistungstest auf einer Variante des Primzahlengenerators von http://docs.cython.org/src/tutorial/numpy.html . Die folgenden Leistungsmaße sind bei kmax = 1000

Pure Python-Implementierung, läuft in CPython: 0.15s

  • Warum nimmt numpy.zeros wenig Platz ein
  • Cython mit Array von Zeigern
  • Cython-Funktion mit variablen Matrix-Input
  • Hat Cython eine vernünftig einfache und effiziente Möglichkeit, Numpy Arrays zu iterieren, als wären sie flach?
  • Cython: unsigned int Indizes für numpy Arrays gibt unterschiedliche Ergebnisse
  • Cython sagt Puffertypen nur als Funktion lokale Variablen auch für ndarray.copy () erlaubt
  • Pure Python-Implementierung, läuft in Cython: 0,07s

    def primes(kmax): p = [] k = 0 n = 2 while k < kmax: i = 0 while i < k and n % p[i] != 0: i = i + 1 if i == k: p.append(n) k = k + 1 n = n + 1 return p 

    Pure Python + Numpy Implementierung, läuft in CPython: 1,25s

     import numpy def primes(kmax): p = numpy.empty(kmax, dtype=int) k = 0 n = 2 while k < kmax: i = 0 while i < k and n % p[i] != 0: i = i + 1 if i == k: p[k] = n k = k + 1 n = n + 1 return p 

    Cython-Implementierung mit int *: 0,003s

     from libc.stdlib cimport malloc, free def primes(int kmax): cdef int n, k, i cdef int *p = <int *>malloc(kmax * sizeof(int)) result = [] k = 0 n = 2 while k < kmax: i = 0 while i < k and n % p[i] != 0: i = i + 1 if i == k: p[k] = n k = k + 1 result.append(n) n = n + 1 free(p) return result 

    Das oben ist großartig, sieht aber schrecklich aus, da es zwei Kopien der Daten enthält … also habe ich versucht, es zu reimplementieren:

    Cython + Numpy: 1.01s

     import numpy as np cimport numpy as np cimport cython DTYPE = np.int ctypedef np.int_t DTYPE_t @cython.boundscheck(False) def primes(DTYPE_t kmax): cdef DTYPE_t n, k, i cdef np.ndarray p = np.empty(kmax, dtype=DTYPE) k = 0 n = 2 while k < kmax: i = 0 while i < k and n % p[i] != 0: i = i + 1 if i == k: p[k] = n k = k + 1 n = n + 1 return p 

    Fragen:

    1. Warum ist die numpy Array so unglaublich langsamer als eine Python-Liste, wenn auf CPython laufen?
    2. Was habe ich in der Cython + Numpy-Implementierung falsch gemacht? Cython ist offensichtlich nicht behandeln die numpy Array als int [] wie es sollte.
    3. Wie gebe ich ein numpy Array auf ein int *? Die unten funktioniert nicht

       cdef numpy.nparray a = numpy.zeros(100, dtype=int) cdef int * p = <int *>a.data 

  • Python Mogo ImportError: kann nicht importieren Name Verbindung
  • Pymongo.errors.CursorNotFound: Cursor-ID '...' ist nicht gültig am Server
  • Tornado "Fehler: [Errno 24] Zu viele offene Dateien" Fehler
  • Wie verwende ich Pymongo, um eine bestehende Dokumentensammlung / db zu verbinden?
  • Switch-Sammlung in der Mongoengine für die Suchanfrage
  • Wie atomar sind die Operationen des mongoengines
  • 3 Solutions collect form web for “Cpython vs cython vs numpy Array Leistung”

     cdef DTYPE_t [:] p_view = p 

    Verwenden Sie diese anstelle von p in den Berechnungen. Reduziert die Laufzeit von 580 ms auf 2,8 ms für mich. Über die exakt gleiche Laufzeit wie die Implementierung mit * int. Und das ist ungefähr das max, das man von diesem erwarten kann.

     DTYPE = np.int ctypedef np.int_t DTYPE_t @cython.boundscheck(False) def primes(DTYPE_t kmax): cdef DTYPE_t n, k, i cdef np.ndarray p = np.empty(kmax, dtype=DTYPE) cdef DTYPE_t [:] p_view = p k = 0 n = 2 while k < kmax: i = 0 while i < k and n % p_view[i] != 0: i = i + 1 if i == k: p_view[k] = n k = k + 1 n = n + 1 return p 

    Warum ist die numpy Array so unglaublich langsamer als eine Python-Liste, wenn auf CPython laufen?

    Weil du es nicht ganz eingegeben hast. Benutzen

     cdef np.ndarray[dtype=np.int, ndim=1] p = np.empty(kmax, dtype=DTYPE) 

    Wie gebe ich ein numpy Array auf ein int *?

    Durch die Verwendung von np.intc als dtype, nicht np.int (das ist ein C long ). Das ist

     cdef np.ndarray[dtype=int, ndim=1] p = np.empty(kmax, dtype=np.intc) 

    (Aber wirklich, verwenden Sie eine Memoryview, sie sind viel sauberer und die Cython-Leute wollen die NumPy-Array-Syntax auf lange Sicht loswerden.)

    Beste Syntax habe ich bisher gefunden:

     import numpy cimport numpy cimport cython @cython.boundscheck(False) @cython.wraparound(False) def primes(int kmax): cdef int n, k, i cdef numpy.ndarray[int] p = numpy.empty(kmax, dtype=numpy.int32) k = 0 n = 2 while k < kmax: i = 0 while i < k and n % p[i] != 0: i = i + 1 if i == k: p[k] = n k = k + 1 n = n + 1 return p 

    Beachten Sie, wo ich numpy.int32 anstelle von int verwendet habe. Alles auf der linken Seite eines cdef ist ein C-Typ (also int = int32 und float = float32), während alles auf der rechten Seite davon (oder außerhalb eines cdef) ein Python-Typ ist (int = int64 und float = float64 )

    Python ist die beste Programmiersprache der Welt.