Seite 1 von 1
for-loop auf lösen für speed up
Verfasst: Mittwoch 14. August 2013, 13:38
von schneitzmaster
Hallo liebes Forum,
ich habe eine for-Schleife die über eine sehr große anzahl an Elementen geht, so dass es ungemein lange dauert bis die operation fertig ist. Dabei soll nichts berechent werden sondern lediglich eine art sortierung vorgenommen werden.
Meine Frage ist es nun ob das ganze in Python auch ohne for-schleife möglich wäre (da die Zuordnung gerade zu trivial ist)
Code: Alles auswählen
pc_elem_seq = [0]*len(PC_SET.elements)
i = 0
for element in PC_SET.elements:
pc_elem_seq[i] = PC_ABS.elements[element.label-1:element.label]
i = i+1
Gruß
Re: for-loop auf lösen für speed up
Verfasst: Mittwoch 14. August 2013, 13:50
von BlackJack
@schneitzmaster: Das Vorgehen an sich sieht schon ziemlich „unpythonisch” aus. Eine Liste mit Dummy-Werten erzeugen und die dann alle der Reihe nach über einen Index mit den echten Werten zu ersetzen ist kein idiomatisches Python. Man würde eine Liste durch anhängen von Elementen an eine anfangs leere Liste erstellen. In diesem Fall würde sich auch eine „list comprehension” geradezu anbieten.
Code: Alles auswählen
pc_elements = [
PC_ABS.elements[element.label - 1:element.label]
for element in PC_SET.elements
]
Edit: Eigentlich sollte das hier reichen falls `PC_ABS.elements` eine Liste ist:
Code: Alles auswählen
pc_elements = [
[PC_ABS.elements[element.label - 1]] for element in PC_SET.elements
]
Es sei denn Du erwartest, dass `label`-Indizes ausserhalb von der Sequenz liegen, auf die dort zugegriffen wird. Wobei die Struktur auf den ersten Blick schon etwas komisch aussieht, die da erzeugt wird.
Re: for-loop auf lösen für speed up
Verfasst: Mittwoch 14. August 2013, 14:16
von schneitzmaster
hi BlackJack,
leider funktioniert dein Vorschlag nicht. Das Problem ist, dass ich die Elemente von
in einer komischen Art und Weise angegeben werden müssen (ich benutze Python als skript-Sprache für ABAQUS CAE).
Hier ein kurzes Beispiel zur Illustration
Code: Alles auswählen
>>> PC_SET.elements[0]
mdb.models['3D-Zelle'].parts['PC_ABS'].elements[2164]
>>> PC_SET.elements[1]
mdb.models['3D-Zelle'].parts['PC_ABS'].elements[2165]
>>> PC_SET.elements[0].label
2165
>>> PC_SET.elements[1].label
2166
>>> pc_elem_seq[0]
mdb.models['3D-Zelle'].rootAssembly.instances['PC_ABS'].elements[2164:2165]
Ich benötige also eine Sequenz in der die elemente mit dem : angegeben sind. Ich weiß nicht genau warum und was der Doppelpunkt in der letzten Zeile zu sagen hat, aber ich denke das ist eine Vorgabe von ABAQUS.
Weiterhin habe ich die Variante mit dem .append schon probiert (das sollte dann etwas mehr "pythonisch" sein).
Code: Alles auswählen
pc_elem_seq = []
for element in PC_SET.elements:
pc_elem_seq.append( PC_ABS.elements[element.label-1:element.label] )
Ich hatte nur vermutet, dass man die Geschwindigkeit der for-schleife noch erhöhen kann wenn man den Speicherplatz vorher allokiert ( wie das in MATLAB gängige Praxis ist).
Aber alle deine Vorschläge sind ja auch mit einer for-schleife versehen. Vielleicht gibt es ja keine andere Möglichkeit. Ich hatte nur gedacht das ich diese zu Ordnung jedes einzelnen Elements ohne for-Schleife durchführen kann. Diese benötigt nämlich die meiste Zeit.
Re: for-loop auf lösen für speed up
Verfasst: Mittwoch 14. August 2013, 14:39
von EyDu
schneitzmaster hat geschrieben:leider funktioniert dein Vorschlag nicht.
Was heißt den "funktioniert nicht"? Gibt es eine Fehlermeldung?
schneitzmaster hat geschrieben:Ich benötige also eine Sequenz in der die elemente mit dem : angegeben sind. Ich weiß nicht genau warum und was der Doppelpunkt in der letzten Zeile zu sagen hat, aber ich denke das ist eine Vorgabe von ABAQUS.
Das nennt sich Slicing und hat mit ABQAUS erstmal nichts zu tun. Hast du schon das offizielle Python-Tutorial durchgearbeitet?
schneitzmaster hat geschrieben:Weiterhin habe ich die Variante mit dem .append schon probiert[/code]
Warum initialisierst du mit [0]?
schneitzmaster hat geschrieben:Aber alle deine Vorschläge sind ja auch mit einer for-schleife versehen. Vielleicht gibt es ja keine andere Möglichkeit. Ich hatte nur gedacht das ich diese zu Ordnung jedes einzelnen Elements ohne for-Schleife durchführen kann. Diese benötigt nämlich die meiste Zeit.
Irgendwo brauchst du auf jeden Fall so etwas wie eine for-Schleife. Egal ob nun explizit oder verdeckt durch ``map``.
Re: for-loop auf lösen für speed up
Verfasst: Mittwoch 14. August 2013, 14:46
von schneitzmaster
Okay gut danke. Das ist eine wertvolle Information. Mit dem Slicing das wusste ich noch nicht.
Nein das Tutorial habe ich noch nicht gemacht.
Und ja es gibt eine Fehler Meldung, da ABAQUS die Elemente in dieser "geslicten" Form haben möchte. Ansonsten wird das ABAQUS interne SET, dass ich erzeugen möchte nicht erzeugt wird.
Ich hatte vermuttet das es einen schnellen weg ohne for-schleife gibt, da ich ja schon alle elemente in dem Object PC_SET.elements drin habe und nur noch in die geslicte Form bringen muss.
Na ja aber wenn du meinst eine for-schleife lässt sich nicht umgehen, denke ich auch dass wohl keinen merklichen Geschwindigkeitszuwachs geben wird oder?
Re: for-loop auf lösen für speed up
Verfasst: Mittwoch 14. August 2013, 14:54
von snafu
@schneitzmaster: Wenn du mit allen Listenelementen irgendwas machen willst, dann müssen eben auch alle Listenelemente abgelaufen werden. Das wird am Ende immer auf eine Schleife hinauslaufen.
Wie EyDu schon angedeutet hatte, mag es - je nach Situation - irgendwelche Python-Funktionen geben, die keine explizite `for`-Schleife in Python-Code erfordern, aber unter der Haube ist letzten Endes trotzdem eine Schleife nötig.
Re: for-loop auf lösen für speed up
Verfasst: Mittwoch 14. August 2013, 15:05
von schneitzmaster
@snafu: Schon klar das am ende immer irgendwie eine Schleife durchläuft. Jedoch gibt es ja zum Beispiel beim bilden eines Skalarproduktes auch mehrere möglichkeiten. Und wenn man da numpy.dot(...) verwendet ist das ja um Größenordnungen schneller als Schleifen zu benutzen. Von daher dachte ich gibt es vielleicht auch fortgeschrittene module oder vorgehensweisen die listen / sequenzen Operationen beschleunigen.
Aber gut ich werd mich mit der Schleife abfinden und in der zwischen Zeit einen Tee trinken

Re: for-loop auf lösen für speed up
Verfasst: Mittwoch 14. August 2013, 15:29
von BlackJack
@schneitzmaster: `numpy.dot()` ist schlecht mit so etwas vergleichbar. Da werden intern Operationen auf Werten von „Prozessor-Datentypen” in reinem C-Code (oder manchmal auch Fortran-Code) und je nach Prozessor vielleicht auch noch parallelisiert, ausgeführt.
Wenn das mit einer ``for``-Schleife und `append()` funktioniert, dann kannst Du auch eine äquivalente „list comprehension” (LC) schreiben. Mein erstes Beispiel sollte da eigentlich funktionieren. Da wird ja noch „slicing” verwendet. Eine LC ist auch ein ganz kleines bisschen schneller als eine ``for``-Schleife. Ohne unleserlich zu werden, dürfte wohl folgendes in reinem Python das Limit darstellen:
Code: Alles auswählen
elements = PC_ABS.elements
pc_elements = [
elements[element.label - 1:element.label] for element in PC_SET.elements
]
Nächster Schritt wäre dann Cython, um den Mehraufwand des Bytcode-Interpretierens zu vermeiden. Wobei das nicht allzu viel bringen dürfte.
Das ganze steckt hoffentlich in einer Funktion‽ Davon abgesehen, dass das sauberer ist, werden lokale Namen auch schneller aufgelöst als (modul)globale Namen.
Dein Beispiel zur Illustration hilft übrigens nicht viel weiter weil alles was mit `PC_SET` zu tun hat, nicht relevant ist. Einzig die letzten beiden Zeilen zeigen das gewünschte Ergebnis. Du möchtest in der Liste also keine Elemente aus `PC_ABS.elements` haben, sondern ein „slice” von diesem Objekt welches immer genau ein Element enthält.
Re: for-loop auf lösen für speed up
Verfasst: Mittwoch 14. August 2013, 15:48
von snafu
Wo genau soll denn jetzt eigentlich die eingangs genannte Sortierung sein? Da werden doch im Grunde nur Objekt-Referenzen rumkopiert oder übersehe ich etwas entscheidendes?
Re: for-loop auf lösen für speed up
Verfasst: Mittwoch 14. August 2013, 16:08
von BlackJack
@snafu: Die Reihenfolge in `PC_SET.elements` beziehungweise die `label`-Attribute dort bestimmen die Reihenfolge des Ergebnisses. Die Ergebniselemente sind ja nicht aus `PC_SET.elements` sondern aus `PC_ABS.elements`.
Re: for-loop auf lösen für speed up
Verfasst: Mittwoch 14. August 2013, 17:44
von snafu
Ich hab keine Ahnung ob's schneller ist und ist ungetestet, da ich die angesprochene Umgebung nicht installiert habe. Rein theoretisch müsste es aber funktionieren:
Code: Alles auswählen
from itertools import imap
from operator import attrgetter
import numpy as np
labels = imap(attrgetter('label'), PC_SET.elements)
choices = np.fromiter(labels, int, len(PC_SET.elements))
print np.choose(choices, PC_ABS.elements)
Re: for-loop auf lösen für speed up
Verfasst: Mittwoch 14. August 2013, 18:27
von BlackJack
@snafu: Ich glaube es macht wenig Sinn `numpy` für so etwas zu missbrauchen. Es geht hier um Objekte und nicht um Arrays von Zahlen. Ausserdem dürfte `numpy.choose()` wohl kaum „slicen”, also ist das keine funktionierende Lösung.
Re: for-loop auf lösen für speed up
Verfasst: Mittwoch 14. August 2013, 19:40
von snafu
BlackJack hat geschrieben:Ausserdem dürfte `numpy.choose()` wohl kaum „slicen”, also ist das keine funktionierende Lösung.
Wenn denn Slicing wirklich gewollt ist...
Naja, PyPy wäre natürlich noch eine naheliegende Alternative. Fragt sich nur, ob der Threadersteller den benutzten Interpreter in seiner Anwendung auch entsprechend auf PyPy umstellen könnte.
Re: for-loop auf lösen für speed up
Verfasst: Mittwoch 14. August 2013, 20:15
von pillmuncher
@schneitzmaster: Aus deinen Beispielen geht nicht hervor, ob am Ende alle Ergebnisse tatsächlich als Sequenz vorliegen müssen, weil du zB. darüber iterieren und alle weiterverarbeiten möchtest, oder ob es genügt, einen Zugriff auf einzelne Ergebnisse zu haben. In diesem Fall könntest du dir das vorherige Erzeugen aller Ergebnisse sparen:
Code: Alles auswählen
class LazyElements(dict):
def __init__(self, pc_abs_elements, pc_set_elements):
slf.pc_abs_elements = pc_abs_elements
slf.pc_set_elements = pc_set_elements
def __missing__(self, key):
index = self.pc_set_elements[key].label
value = self[key] = self.pc_abs_elements[index - 1 : index]
return value
pc_elements = LazyElements(PC_ABS.elements, PC_SET.elements)
print pc_elements[0]
Hierbei werden immer nur die Werte erzeugt, die du auch tatsächlich verwendest, und das Erzeugen geschieht jeweils nur einmal, da alle erzeugten Werte
memoized werden. Informationen zu dicts gibt es
hier. Iterieren wie über eine fertige Sequenz ist damit natürlich nicht mehr möglich.
Re: for-loop auf lösen für speed up
Verfasst: Mittwoch 14. August 2013, 20:26
von Sirius3
ich denke auch nicht, dass die for-Schleife an sich die Sache so langsam macht (Listen mit einigen Millionen Elementen hin und herzuiterieren sollte in wenigen Sekunden machbar sein), sondern das Erzeugen dieser ominösen ABACUS-Sequence-Objekte.
Re: for-loop auf lösen für speed up
Verfasst: Mittwoch 14. August 2013, 20:29
von BlackJack
@snafu: Ja, slicing ist tatsächlich gewollt, weil da ein anderer Typ zurück gegeben wird als bei einem einfachen Indexzugriff, und offenbar wird genau der Typ im weiteren Verlauf benötigt.