Wie optimieren Sie diesen Code (ohne Vektorisierung, da dies die Semantik der Berechnung mit bis führt, die oft weit entfernt, nicht-triviale):Schnelle Numpy Loops
slow_lib.py:
import numpy as np
def foo():
size = 200
np.random.seed(1000031212)
bar = np.random.rand(size, size)
moo = np.zeros((size,size), dtype = np.float)
for i in range(0,size):
for j in range(0,size):
val = bar[j]
moo += np.outer(val, val)
Der Punkt ist, dass solche Art Schleifen ziemlich häufig Operationen entsprechen, wo Sie Doppelsummen über einige Vektoroperation haben. Diese
ist ziemlich langsam:
>>t = timeit.timeit('foo()', 'from slow_lib import foo', number = 10)
>>print ("took: "+str(t))
took: 41.165681839
Ok, also dann ist es lassen cynothize und Typ Anmerkungen hinzufügen mag es kein Morgen:
c_slow_lib.pyx:
import numpy as np
cimport numpy as np
import cython
@cython.boundscheck(False)
@cython.wraparound(False)
def foo():
cdef int size = 200
cdef int i,j
np.random.seed(1000031212)
cdef np.ndarray[np.double_t, ndim=2] bar = np.random.rand(size, size)
cdef np.ndarray[np.double_t, ndim=2] moo = np.zeros((size,size), dtype = np.float)
cdef np.ndarray[np.double_t, ndim=1] val
for i in xrange(0,size):
for j in xrange(0,size):
val = bar[j]
moo += np.outer(val, val)
>>t = timeit.timeit('foo()', 'from c_slow_lib import foo', number = 10)
>>print ("took: "+str(t))
took: 42.3104710579
... ehr ... was? Numba zur Rettung!
numba_slow_lib.py:
import numpy as np
from numba import jit
size = 200
np.random.seed(1000031212)
bar = np.random.rand(size, size)
@jit
def foo():
bar = np.random.rand(size, size)
moo = np.zeros((size,size), dtype = np.float)
for i in range(0,size):
for j in range(0,size):
val = bar[j]
moo += np.outer(val, val)
>>t = timeit.timeit('foo()', 'from numba_slow_lib import foo', number = 10)
>>print("took: "+str(t))
took: 40.7327859402
Also gibt es wirklich keine Möglichkeit, dies zu beschleunigen? Der Punkt ist:
- wenn ich die innere Schleife in eine vektorisierte Version (Gebäude eine größere Matrix, die die innere Schleife und dann ruft np.outer auf der größeren Matrix) umwandeln ich viel schnelleren Code.
- Wenn ich etwas Ähnliches in Matlab (R2016a) implementiere, wird dies durch JIT recht gut.
Weder Cython noch Jit beschleunigen, da Sie bereits C-Code ausführen (über np.outer). Das Problem hier ist eigentlich die Schleife selbst, Sie müssen ihre innere Struktur ändern, damit diese Methoden tatsächlich beschleunigt werden können. – pekapa
Ich weiß, dass die Vektorisierung der inneren (oder beider) Schleifen den Code signifikant beschleunigen wird. Mein Punkt ist, dass die Schleife offensichtlich einen signifikanten Overhead erzeugt, der nicht da sein sollte. Mit anderen Worten: Warum ist np.outer 200-mal so viel langsamer anzurufen als np.outer einmal auf einer Matrix mit sagen wir 200 Reihen (vektorisieren) im Gegensatz zu Matlab-Schleife zu sagen, wo dies ein Nicht-Problem ist ... And Wie kann das überwunden werden? – ndbd
Ich glaube nicht, dass ich weiterhelfen kann, aber werfen Sie einen Blick auf diese Antwort darüber, wie jeder (Python und Matlab) Schleifen behandelt: http: // stackoverflow.com/a/17242928/2752305 – pekapa