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

  • Effiziente Berechnung der Summe der quadratischen Unterschiede
  • Cython: cimport und import numpy als (beide) np
  • Cython: sind typisierte Erinnerungsbilder der moderne Art, um numpy Arrays zu schreiben?
  • Cython mit Array von Zeigern
  • Eine vektorisierte, numpige Funktion zu verhalten, verhält sich wie ein ufunc
  • Zugriff auf NumPy-Datensatz-Array-Spalten in Cython
  • 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 

  • Setzen Sie ein Pandas Dataframe in mongodb mit PyMongo ein
  • Wie bekomme ich eine Liste von nur die ObjectId's mit Pymongo?
  • Lege das $ currentDate auf mongodb mit pymongo ein
  • Mongodb Datenstatistik Visualisierung mit Matplotlib
  • Benutzerdefinierte _id Felder Django MongoDB MongoEngine
  • Mongoengine ... Abfrage etwas nicht in einem ListField?
  • 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.