2017-01-12 5 views
0

Ich habe Probleme mit der Optimierung der folgenden for-Schleifen. Ich habe in die Map-Funktion, Verständnisausdrücke und ein bisschen Itertools und Generatoren geschaut, bin aber unsicher, wie man sich der Optimierung für verschachtelte Schleifen nähert. Jede Hilfe oder Vorschläge wird sehr geschätzt. Danke im Voraus!Optimieren von verschachtelten Python für Schleifen?

Beachten Sie, dass Architektur-Objekt ist:

self.variables.parameters.index1/index2/value 
self.variables.rate 
self.state.num 

Loop 1:

mat1 = np.zeros(m, n) 
for idx, variable in enumerate(self.variables): 
    for parameter in variable.parameters: 
     tracking_idx = parameter.index1 + parameter.index2 
     mat1[tracking_idx, idx] = parameter.value 

Loop 2:

mat2 = [] 
for variable in self.variables: 
    rate = variable.rate 
    for parameter in variable.parameters: 
     if parameter.value < 0 and self.state.num[parameter.index1, parameter.index2] <= 0: 
      rate = 0 
    mat2.append(rate) 
+1

Für die zweite Schleife, wenn Sie eine große Anzahl von Parametern haben, kann das Hinzufügen einer Pause nach der Rate = 0 Anweisung helfen, da es die Überprüfung der anderen Parameter stoppt –

Antwort

1

Mit einem numpy Tag Ich gehe davon aus 'optimize' bedeutet, diese Schleifen werfen als kompilierte numpy Array-Ausdrücke. Ich denke nicht, dass es einen Weg gibt, ohne zuerst alle Daten als numpige Arrays zu sammeln, die die gleichen Schleifen benötigen.

Sie haben eine Liste von nvariables. Jede Variable hat eine Liste von ? Parametern. Jeder Parameter hat 3 oder 4 Attribute.

So ist

rates = np.array([v.rate for v in variables]) 
values = np.array([[p.value for p in v.parameters] for v in variables] 
index1s = <dito> (?,n) array 
index2s = <dita> (?,n) array 

self.state.num bereits ein 2D-Array, Größe kompatibel mit dem Wertebereich in index1s und index2s.

Angesichts dieser 1 und 2d-Arrays sollten wir mat1 und mat2 mit ganzen Array-Operationen ableiten können. Wenn ? klein ist relativ zu m und der Bereich der Werte in index1 und index2 könnte es sich lohnen, dies zu tun. Ich habe kein realistisches Gefühl für Ihre Daten.

===========

Sie erwähnen the map function, comprehension expressions, and a bit of itertools and generators. Diese können den Code etwas sauberer erscheinen lassen, machen aber keinen großen Unterschied in der Geschwindigkeit.

Ich habe die Verwendung von List Comprehensions demonstriert. Diese Ausdrücke können komplizierter sein, aber oft auf Kosten der Lesbarkeit. Ich mag es, Hilfsfunktionen zu schreiben, um Details zu verbergen. Ein Generatorverständnis kann ein Listenverständnis ersetzen, das ein anderes füttert. Karten decken die gleiche Funktionalität ab.

Da variables und parameters Attribute haben, nehme ich an, dass Sie sie in Klassen definiert haben. Sie könnten Methoden schreiben, die diese Attribute als einfache Listen oder Arrays extrahieren.

class Variable(....): 
    .... 
    def get_values(self): 
     return [p.value for p in self.parameters] 
    def get_rate(self, state): 
     rate = self.rate 
     for parameter in self.parameters: 
      if parameter.value < 0 and     
       state.num[parameter.index1, parameter.index2] <= 0: 
      rate = 0 
     return rate 

values = [v.get_values() for v in variables] 
rates = [v.get_rate(self.state) for v in variables] 

Sie könnten diese Hilfsfunktion auch ohne die Klassenstruktur schreiben.

Das beschleunigt nichts; Es verbirgt nur einige Details im Objekt.

+0

Danke! Ich benutzte ein Listenverständnis für Mat1 und behielt die for-Schleife für Mat2. Es reduzierte die Laufzeit um 20% oder so! – tooty44

Verwandte Themen