Effizientes äußeres Produkt in Python

8

Äußeres Produkt in Python scheint ziemlich langsam zu sein, wenn wir mit Vektoren der Dimension der Ordnung 10k umgehen müssen. Könnte mir bitte jemand eine Idee geben, wie könnte ich diese Operation in Python beschleunigen?

Code ist wie folgt:

%Vor%

Da ich diese Operation mehrmals ausführen muss, wird mein Code langsamer.

    
thetna 07.01.2015, 00:16
quelle

3 Antworten

23

Es wird nicht wirklich schneller als das, das sind Ihre Möglichkeiten:

numpy.outer

%Vor%

numpy.einsum

%Vor%

numba

%Vor%

Sittich

%Vor%

Cython

%Vor%

theano

%Vor%

pypy

%Vor%

Schlussfolgerungen:

%Vor%     
elyase 07.01.2015, 01:02
quelle
4

@ elyases Antwort ist großartig und wird zu Recht angenommen. Hier ist ein zusätzlicher Vorschlag, der, wenn Sie ihn verwenden können, den Aufruf von np.outer noch schneller machen könnte.

Sie sagen: "Ich muss diese Operation mehrmals ausführen", daher ist es möglich, dass Sie das Array, das das äußere Produkt enthält, wiederverwenden können, anstatt jedes Mal ein neues zuzuweisen. Das kann einen schönen Schub in der Leistung geben.

Zunächst einige zufällige Daten, mit denen gearbeitet werden kann:

%Vor%

Hier ist das Basis-Timing für np.outer (a, b) auf meinem Computer:

%Vor%

Angenommen, wir wiederholen diese Operation mehrmals mit Arrays gleicher Form. Erstellen Sie ein out -Array, um das Ergebnis zu speichern:

%Vor%

Verwenden Sie nun out als drittes Argument von np.outer :

%Vor%

Sie erhalten also einen schönen Leistungsschub, wenn Sie das Array, das das äußere Produkt enthält, wiederverwenden können.

Sie erhalten einen ähnlichen Vorteil, wenn Sie das Argument out von einsum verwenden und in der Cython-Funktion ein drittes Argument für die Ausgabe hinzufügen, anstatt es in der Funktion mit np.empty zuzuweisen. (Die anderen compiled / jitted-Codes in @elyase's Antwort werden wahrscheinlich auch davon profitieren, aber ich habe nur die Cython-Version ausprobiert.)

Nota bene! Der oben gezeigte Nutzen wird in der Praxis möglicherweise nicht realisiert. Das Array out passt in den L3-Cache meiner CPU, und wenn es in der Schleife verwendet wird, die vom Befehl timeit ausgeführt wird, bleibt es wahrscheinlich im Cache. In der Praxis könnte das Array zwischen Aufrufen von np.outer aus dem Cache verschoben werden. In diesem Fall ist die Verbesserung nicht so dramatisch, aber es sollten dennoch zumindest die Kosten eines Aufrufs von np.empty() sein, d. H.

%Vor%     
Warren Weckesser 07.01.2015 05:48
quelle
2

Es sollte so einfach sein wie numpy.outer() : eine einzige Funktionsaufruf, der in C für hohe Leistung implementiert wird.

    
John Zwinck 07.01.2015 00:24
quelle

Tags und Links