Ich würde gerne wissen, wie ich dieses Problem umwandeln könnte, um den Overhead der np.sum()
Funktionsaufrufe in meinem Code zu reduzieren.Code Optimierung - Anzahl der Funktionsaufrufe in Python
Ich habe eine input
Matrix, sagen wir von shape=(1000, 36)
. Jede Zeile repräsentiert einen Knoten in einem Diagramm. Ich habe eine Operation, die ich mache, die über jede Zeile iteriert und eine elementweise Addition zu einer variablen Anzahl anderer Zeilen ausführt. Diese "anderen" Zeilen sind in einem Verzeichnis nodes_nbrs
definiert, das für jede Zeile eine Liste von Zeilen aufzeichnet, die zusammen summiert werden müssen. Ein Beispiel dafür ist als solche:
nodes_nbrs = {0: [0, 1],
1: [1, 0, 2],
2: [2, 1],
...}
Hier Knoten 0
in die Summe von Knoten transformiert werden würde und 0
1
. Der Knoten 1
würde in die Summe der Knoten 1
, 0
und 2
umgewandelt werden. Und so weiter für den Rest der Knoten.
Die aktuelle (und naive) Art, die ich derzeit implementiert habe, ist als solche. Ich zum ersten Mal eines Null-Array der endgültigen Form instanziiert, die ich will, und dann im nodes_nbrs
Wörterbuch über jeden Schlüssel-Wert-Paar iterieren:
output = np.zeros(shape=input.shape)
for k, v in nodes_nbrs.items():
output[k] = np.sum(input[v], axis=0)
Dieser Code ist alles kühl und fein in kleinen Tests (shape=(1000, 36)
), aber Bei größeren Tests (shape=(~1E(5-6), 36)
) dauert es ~ 2-3 Sekunden. Ich muss diese Operation tausendmal durchführen, also versuche ich, ob es einen optimierten Weg gibt.
Nachdem ich Linienprofilierung gemacht habe, habe ich festgestellt, dass der Schlüsselkiller hier die np.sum
Funktion immer und immer wieder aufruft, was etwa 50% der Gesamtzeit beansprucht. Gibt es eine Möglichkeit, diesen Overhead zu eliminieren? Oder gibt es eine andere Möglichkeit, dies zu optimieren?
aus, dass Apart, hier ist eine Liste der Dinge, die ich getan habe, und (sehr kurz) ihre Ergebnisse:
- A
cython
Version: entfällt diefor
Art Schleife Kopf Überprüfung, 30% Ermäßigung in der Zeit genommen. Bei dercython
-Version benötigtnp.sum
etwa 80% der gesamten Wanduhrzeit statt 50%. - Deklarieren Sie
np.sum
als Variablenpsum
, und rufen Sienpsum
innerhalb derfor
Schleife. Kein Unterschied zum Original. - Ersetzen
np.sum
mitnp.add.reduce
, und daß an die Variablenpsum
, zuweisen und dann im Inneren desnpsum
for
Schleife aufzurufen. ~ 10% Reduzierung der Wanduhrzeit, aber dann inkompatibel mitautograd
(Erklärung unten in spärlichen Matrizen Aufzählungspunkt). numba
JIT-ing: nicht mehr als das Hinzufügen von Decorator versucht. Keine Verbesserung, aber ich habe mich nicht angestrengt.- Konvertieren Sie das
nodes_nbrs
Wörterbuch in ein dichtesnumpy
Binärarray (1s und 0s), und führen Sie dann eine einzelnenp.dot
Operation. Gut in der Theorie, schlecht in der Praxis, weil es eine quadratische Matrix vonshape=(10^n, 10^n)
erfordern würde, die in der Speichernutzung quadratisch ist.
Dinge, die ich habe nicht versucht, aber ich bin zögerlich, dies zu tun:
scipy
Sparse-Matrizen: Ichautograd
verwende, die nicht automatische Differenzierung derdot
Betrieb unterstützt fürscipy
Sparse-Matrizen.
Für diejenigen, die neugierig sind, ist dies im Wesentlichen eine Faltungsoperation auf die Grafik-strukturierte Daten. Irgendwie macht es Spaß, dies für die Schule zu entwickeln, aber auch etwas frustrierend, wenn man an der Spitze des Wissens ist.
Eine Sache, die aus Ihrem Beispiel springt, ist das Konzept, dass einige der Kompositionen Teilmengen von anderen sind. Zum Beispiel haben Sie '0: [0,1]' und auch '1: [1,0,2]'. In einer geraden Summe würde das bedeuten, dass Sie 0 berechnen und dann 1 als 0-Primzahl plus 2-Original berechnen könnten. Dies würde die Anzahl der Aufrufe von "np.sum" nicht reduzieren, könnte aber den Aufruf selbst verkürzen. Hat das in Ihrem Fall einen "echten" Wert? –
@AustinHstings: Vielen Dank für Ihre Antwort! Ja, Sie haben Recht, dass es einige Kompositionen gibt, die Teilmengen sind, und andere, die sich durch einige Teilmengen überlappen können. Ich denke, es ist einen Versuch wert. Die einzige Sorge, die ich gerade habe, ist, dass der Overhead der Datenverarbeitung, welche Mengen Überlappungen/Teilmengen sind, die Leistungsgewinne überwiegen kann, besonders wenn es Hunderte und Tausende von Zeilen gibt. Was sind deine Gedanken? – ericmjl
Ich denke das hängt davon ab (a) wie "berechenbar" die Überlappungen sind; und (b) welchen Prozess Sie verwenden, um Ihr Diktat zu generieren. Es kann der Fall sein, dass die Überlappungen wirklich billig ausfallen, weil Sie eine bestimmte Art von Traverse oder etwas ähnliches tun. –