python optimieren

Moin

Ich hab hier ein script das extrem lange Laufzeit hat.
Ich konnte es von 600 Jahren schon auf 9 Tage optimieren :wink:

Ein script jeder gegen jeden und auch gegen sich selbst, die Ergebnisse werden in einer Datenbank gespeichert.
Die Liste Kombination hat ~160000 Einträge, das sind alleine schon 12 Milliarden Durchläufe. Die innere while schleife produziert etwa 600 Durchläufe, kommt darauf an.
Wenn die Trefferpunkte 300 sind und der Rundenschaden 0.5.
Wie kann ich hier weiter optimieren?
Vielleicht auch mathematisch korrekt die inneren werte reduzieren, sodass weniger Durchläufe entstehen.
Ich benutze jetzt schon cython, geht da noch mehr?

http://pastebin.com/XiyL7smN
 
Zuletzt bearbeitet:
Zum einen kann das Laufen lassen in PyPy schon wahre Wunder bewirken:
PyPy
insbesondere bei Schleifen und simplen Rechenvorgängen.
(PyPy=Python mit JIT Compiler, hinkt allerdings der aktuellen Python Entwicklung etwas hinterher. Mit "Laufen lassen" meine ich kein Umschreiben in RPython oder ähnliches, sondern statt "python myfile.py" eben "pypy myfile.py" nutzen ;))

Dann:
die innere "while True" Schleife kann man sich doch komplett sparen:
Hier möchtest Du doch nur wissen, wer zuerst stirbt, richtig?
Code:
def_dies_after = Trefferpunkite_verteidiger//rundenschaden_angreifer
attacker_dies_after = Trefferpunkte_angreifer//rundenschaden_verteidiger
if def_dies_after < attacker_dies_after:
    print "Angreifer gewinnt"
elif def_dies_after == attacker_dies_after:
    print "Untentschieden"
else:
    print "Verteidiger gewinnt"

PS: nicht zu vergessen:
Code:
combinations_with_replacement
sollte ein Generator sein (also 1 Ergebnis pro Anfrage liefern und nicht etwa gleich die ganze Liste)
Edit: habe das mit dem Cython überlesen. Würde trotzdem erstmal PyPy probieren ;)
 
For-Schleifen optimiert man in Python laut meinem Pythonbuch durch die map()-Funktion oder list comprehensions.
 
For-Schleifen optimiert man in Python laut meinem Pythonbuch durch die map()-Funktion oder list comprehensions.
Jein. Diese machen nicht immer einen Sinn.
Map möchte schließlich auch eine Liste/Generator/Iterator als Argument haben, um die Funktion auf das jeweilige Item anzuwenden und sowohl Map wie auch list comprehessions würden dann alle 160000 Ergebnisse auf einmal zurückzuliefern - das wäre ein merkbarer Overhead bezüglich des Speichers ;)

Klassisches Beispiel ist range vs xrange
Code:
>>> import timeit
>>> s="""\
...   for i in range(10000000):
...     pass
...
... """
>>> s2="""for i in xrange(10000000):pass"""
>>> t=timeit.Timer(stmt=s)
>>> t2=timeit.Timer(stmt=s2)
>>> t.timeit(1)
1.1947334088550576
>>> t2.timeit(1)
0.55001822857374805
Ganz nett in diesem Zusammenhang sind übrigens die Itertools:
9.7. itertools ? Functions creating iterators for efficient looping — Python v2.7.1 documentation
 
Vielen Dank CDW

Manchmal sieht man über die einfachste Lösung hinweg.. Die Funktion combinations_with_replacement() ist auch aus den Itertools, eine sehr nützliches Modul wie ich finde. Das Script ist jetzt jedenfalls so schnell, dass die Datenbank zum Flaschenhals geworden ist.

Ich überlege die Ergebnisse erstmal im Speicher abzulegen, in Verbindung mit Threads, aber dazu muss ich mir noch einiges anlesen.

Gruß Biervampir
 
Zurück
Oben