Ich verstehe das Konzept dessen, was timeit
funktioniert, bin mir aber nicht sicher, wie ich es in meinem Code implementieren soll.
Wie kann ich vergleichen zwei Funktionen, sagen wir insertion_sort
und tim_sort
mit timeit
?
Die Funktionsweise von timeit besteht darin, den Setup-Code einmal auszuführen und dann eine Reihe von Anweisungen wiederholt aufzurufen . Wenn Sie also die Sortierung testen möchten, ist einige Sorgfalt erforderlich, damit ein Durchgang bei einer direkten Sortierung den nächsten Durchgang mit bereits sortierten Daten nicht beeinflusst (dies würde den Timsort natürlich wirklich zum Leuchten bringen, da er die beste Leistung erbringt wenn die Daten bereits teilweise bestellt sind).
Hier ist ein Beispiel für das Einrichten eines Sortiertests:
>>> import timeit
>>> setup = '''
import random
random.seed('slartibartfast')
s = [random.random() for i in range(1000)]
timsort = list.sort
'''
>>> print min(timeit.Timer('a=s[:]; timsort(a)', setup=setup).repeat(7, 1000))
0.334147930145
Beachten Sie, dass die Anweisungsreihe bei jedem Durchgang eine neue Kopie der unsortierten Daten erstellt.
Beachten Sie auch die Timing-Technik, bei der die Messsuite sieben Mal ausgeführt wird und nur die beste Zeit eingehalten wird. Dies kann wirklich dazu beitragen, Messverzerrungen aufgrund anderer Prozesse auf Ihrem System zu reduzieren.
Das sind meine Tipps für den richtigen Umgang mit timeit. Hoffe das hilft :-)
timsort(a)
und nehmen Sie den Unterschied :-).repeat(7,1000)
bereits tun (indem Sie den gleichen Samen verwenden)! Ihre Lösung ist also IMO perfekt..repeat(7, 1000)
vs..repeat(2, 3500)
vs.repeat(35, 200
) davon abhängen sollte, wie der Fehler aufgrund der Systemlast mit dem Fehler aufgrund der Eingabevariabilität verglichen wird. Im Extremfall, wenn Ihr System immer stark ausgelastet ist und Sie links von der Verteilung der Ausführungszeit einen langen, dünnen Schwanz sehen (wenn Sie es in einem seltenen Leerlaufzustand abfangen), sind Sie möglicherweise sogar.repeat(7000,1)
nützlicher als.repeat(7,1000)
wenn Sie kann nicht mehr als 7000 Läufe budgetieren.Wenn Sie
timeit
in einer interaktiven Python-Sitzung verwenden möchten , gibt es zwei praktische Optionen:Verwenden Sie die IPython- Shell. Es verfügt über die praktische
%timeit
Sonderfunktion:In einem Standard-Python-Interpreter können Sie auf Funktionen und andere Namen zugreifen, die Sie zuvor während der interaktiven Sitzung definiert haben, indem Sie sie aus
__main__
der Setup-Anweisung importieren :quelle
from __main__ import f
Technik. Ich denke nicht, dass dies so bekannt ist, wie es sein sollte. Dies ist in solchen Fällen hilfreich, in denen ein Funktions- oder Methodenaufruf zeitgesteuert wird. In anderen Fällen (zeitliche Abstimmung einer Reihe von Schritten) ist dies weniger hilfreich, da dadurch der Funktionsaufruf-Overhead eingeführt wird.%timeit f(x)
sys._getframe(N).f_globals
) von Anfang an die Standardeinstellung gewesen sein.Ich werde Ihnen ein Geheimnis verraten: Der beste Weg, dies zu tun,
timeit
ist die Befehlszeile.Führt in der Befehlszeile eine
timeit
ordnungsgemäße statistische Analyse durch: Hier erfahren Sie, wie lange der kürzeste Lauf gedauert hat. Dies ist gut, da alle Zeitfehler positiv sind. Die kürzeste Zeit hat also den geringsten Fehler. Es gibt keine Möglichkeit, einen negativen Fehler zu erhalten, da ein Computer niemals schneller rechnen kann als er!Also die Kommandozeilenschnittstelle:
Das ist ganz einfach, oder?
Sie können Folgendes einrichten:
das ist auch nützlich!
Wenn Sie mehrere Zeilen möchten, können Sie entweder die automatische Fortsetzung der Shell verwenden oder separate Argumente verwenden:
Das gibt ein Setup von
und Zeiten
Wenn Sie längere Skripte haben möchten, könnten Sie versucht sein, in
timeit
ein Python-Skript zu wechseln . Ich schlage vor, dies zu vermeiden, da die Analyse und das Timing in der Befehlszeile einfach besser sind. Stattdessen neige ich dazu, Shell-Skripte zu erstellen:Dies kann aufgrund der mehrfachen Initialisierungen etwas länger dauern, aber normalerweise ist das keine große Sache.
Aber was , wenn Sie möchten , verwenden
timeit
in Ihrem Modul?Nun, der einfache Weg ist:
und das gibt Ihnen kumulative ( nicht minimale!) Zeit, um diese Anzahl von Malen auszuführen.
Verwenden Sie, um eine gute Analyse zu erhalten
.repeat
und nehmen Sie das Minimum, :Normalerweise sollten Sie dies mit kombinieren,
functools.partial
anstattlambda: ...
den Overhead zu senken. So könnte man so etwas haben wie:Sie können auch:
das würde Ihnen etwas näher an der Schnittstelle geben von der Kommandozeile geben, aber auf eine viel weniger coole Art und Weise. Mit
"from __main__ import ..."
können Sie Code aus Ihrem Hauptmodul in der von erstellten künstlichen Umgebung verwendentimeit
.Es ist erwähnenswert, dass dies ein Convenience-Wrapper für ist
Timer(...).timeit(...)
und daher nicht besonders gut im Timing ist. Ich persönlich bevorzuge es bei weitem,Timer(...).repeat(...)
wie ich oben gezeigt habe.Warnungen
Es gibt ein paar Einschränkungen
timeit
, die überall gelten.Gemeinkosten werden nicht berücksichtigt. Angenommen, Sie möchten Zeit
x += 1
, um herauszufinden, wie lange das Hinzufügen dauert:Nun, es ist nicht 0,0476 µs. Sie wissen nur, dass es weniger ist . Alle Fehler sind positiv.
Versuchen Sie also, reinen Overhead zu finden:
Das sind gut 30% Overhead, nur vom Timing! Dies kann die relativen Timings massiv verzerren. Aber Sie haben sich nur wirklich um das Hinzufügen von Timings gekümmert ; Die Nachschlagezeiten für müssen
x
ebenfalls im Overhead enthalten sein:Der Unterschied ist nicht viel größer, aber er ist da.
Mutationsmethoden sind gefährlich.
Aber das ist völlig falsch!
x
ist die leere Liste nach der ersten Iteration. Sie müssen neu initialisieren:Aber dann haben Sie viel Aufwand. Berücksichtigen Sie dies separat.
Beachten Sie, dass das Subtrahieren des Overheads hier nur deshalb sinnvoll ist der Overhead nur einen kleinen Bruchteil der Zeit ausmacht.
In Ihrem Beispiel ist anzumerken, dass sowohl Insertion Sort als auch Tim Sort ein völlig ungewöhnliches Timing-Verhalten für bereits sortierte Listen aufweisen. Dies bedeutet, dass Sie eine
random.shuffle
Zwischensortierung benötigen, wenn Sie vermeiden möchten, dass Ihre Timings zerstört werden.quelle
timeit
aus einem Programm zu verwenden, aber genauso wie die Befehlszeile zu funktionieren? .timeit
wird einepass
Anweisung ausgeführt, wenn keine Argumente angegeben werden, was natürlich einige Zeit in Anspruch nimmt. Wenn Argumente angegeben werden,pass
werden diese nicht ausgeführt, daher0.014
wäre es falsch , einige Usecs von jedem Timing zu subtrahieren .Wenn Sie zwei Codeblöcke / Funktionen schnell vergleichen möchten, können Sie Folgendes tun:
quelle
Ich finde, die einfachste Möglichkeit, timeit zu verwenden, ist über die Befehlszeile:
Gegeben test.py :
Führen Sie die Zeit so aus:
quelle
Für mich ist dies der schnellste Weg:
quelle
quelle
Das funktioniert super:
quelle
Lassen Sie uns in jedem der folgenden Wörter das gleiche Wörterbuch einrichten und die Ausführungszeit testen.
Das Setup-Argument richtet im Grunde das Wörterbuch ein
Nummer ist, den Code 1000000 mal auszuführen. Nicht das Setup, sondern das stmt
Wenn Sie dies ausführen, können Sie sehen, dass der Index viel schneller ist als get. Sie können es mehrmals ausführen, um zu sehen.
Der Code versucht grundsätzlich, den Wert von c im Wörterbuch abzurufen.
Hier sind meine Ergebnisse, Ihre werden sich unterscheiden.
nach Index: 0,20900007452246427
von get: 0.54841166886888
quelle
Übergeben Sie einfach Ihren gesamten Code als Argument der Zeit:
quelle
quelle
gc.enable()
?Das integrierte Timeit-Modul funktioniert am besten über die IPython-Befehlszeile.
So steuern Sie Funktionen innerhalb eines Moduls:
quelle
Beispiel für die Verwendung des Python REPL-Interpreters mit einer Funktion, die Parameter akzeptiert.
quelle
Sie würden zwei Funktionen erstellen und dann etwas Ähnliches ausführen. Beachten Sie, dass Sie die gleiche Anzahl von Ausführungen / Ausführungen auswählen möchten, um Apfel mit Apfel zu vergleichen.
Dies wurde unter Python 3.7 getestet.
Hier ist der Code zum einfachen Kopieren
quelle