Ich habe zwei Skripte, die jeweils die Fakultät einer Zahl berechnen. Ich würde gerne wissen, was schneller ist. Der time
Befehl gibt mir Millisekunden und das Ergebnis ist von Zeit zu Zeit unterschiedlich:
piousbox@piousbox-laptop:~/projects/trash$ time ruby fac2.rb
30414093201713378043612608166064768844377641568960512000000000000
real 0m0.089s
user 0m0.052s
sys 0m0.028s
piousbox@piousbox-laptop:~/projects/trash$ time ruby fac1.rb
30414093201713378043612608166064768844377641568960512000000000000
real 0m0.091s
user 0m0.048s
sys 0m0.036s
piousbox@piousbox-laptop:~/projects/trash$ time ruby fac1.rb
30414093201713378043612608166064768844377641568960512000000000000
real 0m0.088s
user 0m0.048s
sys 0m0.040s
piousbox@piousbox-laptop:~/projects/trash$ time ruby fac2.rb
30414093201713378043612608166064768844377641568960512000000000000
real 0m0.088s
user 0m0.048s
sys 0m0.028s
piousbox@piousbox-laptop:~/projects/trash$ time ruby fac1.rb
30414093201713378043612608166064768844377641568960512000000000000
real 0m0.087s
user 0m0.064s
sys 0m0.028s
piousbox@piousbox-laptop:~/projects/trash$ time ruby fac2.rb
30414093201713378043612608166064768844377641568960512000000000000
real 0m0.089s
user 0m0.068s
sys 0m0.016s
piousbox@piousbox-laptop:~/projects/trash$
Wie nehme ich die durchschnittliche Zeit in Anspruch, um das Skript auszuführen? Ich könnte die Ausgabe einer 100er analysieren und mitteln, time
aber ich kann mir vorstellen, dass es eine bessere Lösung gibt.
Antworten:
Nein, Ihre Vorstellung von Durchschnittsbildung ist richtig.
Die Skriptausführung hängt von vielen Faktoren ab. Sie muss jedoch zwischen der Setup-Zeit (Laden des Interpreters in den Speicher, Einrichten und möglicherweise Kompilieren von Code in Bytecode oder Maschinencode) und der tatsächlichen Ausführungszeit aufgeteilt werden.
Um sich besser auf die innere Ausführungszeit zu konzentrieren, führen Sie die Schleife im Skript selbst aus (dh anstatt eine Fakultät zu berechnen, berechnen Sie sie 100 Mal innerhalb einer Ausführung des Skripts. Das Skript wird einmal eingerichtet und die innere Routine wird 100 Mal ausgeführt mal).
Um sich auf die Gesamtzeit zu konzentrieren, führen Sie das Skript hundertmal aus und mitteln die Ergebnisse. Im Idealfall sollten Sie diese Ausführungen so weit trennen, dass das System jedes Mal einen "Referenzstatus" (oder einen Status ohne Skriptbezug) zurückgibt. Beispielsweise wird der Interpreter selbst im Speicher zwischengespeichert, sodass die erste Ausführung des Skripts erheblich langsamer ist als die nachfolgenden.
Um einen besseren Einblick in den Algorithmus zu erhalten, ist meiner Meinung nach der beste Weg (auf einem ansonsten inaktiven Rechner):
Die Anwendung wird nur einmal ausgeführt. Das Setup und das Priming werden bei der ersten nicht zeitgesteuerten Iteration durchgeführt. Dies sollte den Overhead minimieren (mit Ausnahme von möglicherweise zeitgesteuerten Aufrufen).
Wenn die Funktion eine Eingabe empfängt, sollten Sie eine zufällige Folge von Eingaben mit einem PRNG-Seed mit einem festen Wert bereitstellen, um sicherzustellen, dass beide Versionen der getesteten Funktion dieselben Werte erhalten. Dies vermeidet, dass eine Funktion aufgrund von "Glückszahlen" anscheinend besser abschneidet (z. B. erinnere ich mich an eine Variation des Hillsort-Algorithmus, die messbar besser abschneidet, wenn die Anzahl der zu sortierenden Elemente in der Form 2 k –1 mit kleinen k s liegt).
quelle
Sie können Iterationen des Programms in einer Schleife ausführen. und dividieren Sie die Gesamtzeit durch die Anzahl der Iterationen:
quelle
{1..10}
und bin verblüfft, dass es funktioniert. Ich kann es nicht im Bash-Handbuch finden. Das einzig Traurige ist, dass Sie die Verteilung Ihrer Ergebnisse nicht kennen (minimale und maximale Zeit).man -P 'less +/Brace\ Expansion' bash
bash
. Versuche/bin/bash
vorher zu rennen .Es gibt ein Tool namens multitime , das genau das tut: einen Befehl mehrmals ausführen, messen, wie lange es dauert (real / user / system mit Mittelwert, min / max und Medianzeit, die automatisch berechnet werden)
Zum Beispiel, um ein ähnliches Skript 100 Mal zu messen:
quelle
Dies ist alt, aber es tauchte bei Google so hoch auf, als ich nach einem Befehl suchte, den ich zuvor verwendet hatte, aber nicht finden konnte. Wie auch immer, meine bevorzugte Art dies zu tun ist:
Dies enthält eine ganze Reihe von Details, einschließlich der durchschnittlichen Ausführungszeit direkt am Ende:
quelle
Für
-n
,-r
und andere Optionen siehe https://docs.python.org/2/library/timeit.html#command-line-interfacequelle
Hyperfein ist eine weitere Option.
Beispielnutzung:
quelle