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

  • Cython: cimport und import numpy als (beide) np
  • Fadensichere Zufallszahlenerzeugung mit Zython
  • C malloc Array Zeiger Rückkehr in Zython
  • 3D Schiebefenster Betrieb in Theano?
  • Mit scipy.integrate.ode mit Cython
  • Einfache Umwicklung von C-Code mit Zython
  • 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 

  • Wie konvertiere ich einen pymongo.cursor.Cursor in einen Dict?
  • Das JSON-Objekt kann nicht von MongoDB in Python serialisiert werden
  • Importiere JSON zu mongoDB mit pymongo
  • MongoDB + Python - sehr langsame einfache Abfrage
  • Mongo Push zu Array innerhalb Array
  • Anfügen von Element in MongoDB-Dokumentarray in PyMongo ohne Wiedereinführung
  • 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.