Ich bewerte den Ausdruck 6^6^6
mit python
und bc
getrennt.
Der Inhalt der Python-Datei ist print 6**6**6
. Wenn ich ausführe time python test.py
, erhalte ich die Ausgabe als
real 0m0.067s
user 0m0.050s
sys 0m0.011s
Und dann habe ich den Befehl ausgeführt, time echo 6^6^6 | bc
der mir die folgende Ausgabe gab
real 0m0.205s
user 0m0.197s
sys 0m0.005s
Aus diesen Ergebnissen ist klar, dass die von Python und BC benötigte Sys-Zeit 11 ms bzw. 5 ms betrug. Der Befehl bc übertraf Python auf Sys-Zeit-Ebene, war jedoch in Bezug auf Benutzer- und Echtzeit-Python fast viermal schneller als bc . Was könnte dahin gegangen sein. Ich habe den Prozessen als solchen keine Priorität eingeräumt. Ich versuche diese Situation zu verstehen.
python
performance
process-management
bc
Ganessh
quelle
quelle
echo | bc
Dazu gehört das Starten einer Subshell aufgrund der Pipe. Daher stammt wahrscheinlich ein Teil Ihrer zusätzlichen Benutzerzeit. Um dies zu einem gerechten Test zu machen, sollte das Python-Skript von stdin lesen, damit Sie es könnentime echo 6**6**6 | whatever.py
.echo 6^6^6 | time bc
.6**6**6
Ausdruck tatsächlich zur Kompilierungszeit berechnet . Da Sie die Datei jedoch direkt starten, anstatt sie aus einem Modul zu importieren, sollte dies keine Rolle spielen. Um den Unterschied zu sehen , fügen Sie ihn10**12345678
in einea.py
Datei ein und versuchen Sie, ihn aus dem interaktiven Interpreter zu importieren. Schließen Sie dann den Interpreter, starten Sie ihn neu und importieren Sie ihna
erneut. Das erste Mal sollte es eine merkliche Zeit dauern (weil Python das Modul kompiliert), während das zweite Mal das.pyc
, was augenblicklich sein sollte,Antworten:
Python importiert beim Start eine große Anzahl von Dateien:
Jedes dieser Verfahren erfordert eine noch größere Anzahl von Versuchen, eine Python-Datei zu öffnen, da es viele Möglichkeiten gibt, ein Modul zu definieren:
Jeder "Versuch", mit Ausnahme derjenigen, die eingebaut sind, erfordert einen Aufruf auf Betriebssystemebene / System, und jeder "Import" scheint ungefähr 8 "Versuch" -Nachrichten auszulösen. (Es gab Möglichkeiten, dies mit zipimport zu reduzieren, und jeder Pfad in Ihrem PYTHONPATH erfordert möglicherweise einen weiteren Aufruf.)
Dies bedeutet, dass es fast 200 stat-Systemaufrufe gibt, bevor Python auf meinem Computer gestartet wird, und "time" weist dies eher "sys" als "user" zu, da das Benutzerprogramm darauf wartet, dass das System die Dinge ausführt.
Im Vergleich dazu und wie Terdon sagte, hat "bc" nicht so hohe Startkosten. Wenn ich mir die Ausgabe von dtruss ansehe (ich habe einen Mac; "strace" für ein Linux-basiertes Betriebssystem), sehe ich, dass bc keine eigenen open () - oder stat () -Systemaufrufe ausführt, außer ein paar gemeinsam genutzte Bibliotheken sind der Anfang, was natürlich auch Python tut. Darüber hinaus muss Python mehr Dateien lesen, bevor es zur Verarbeitung bereit ist.
Das Warten auf die Festplatte ist langsam.
Sie können ein Gefühl für die Startkosten von Python bekommen, indem Sie Folgendes tun:
Auf meinem Computer sind es 0,032 s, während "print 6 ** 6 ** 6" 0,072 s ist, sodass die Startkosten 1/2 der Gesamtzeit betragen und die Berechnung + Konvertierung in Dezimalzahl die andere Hälfte ist. Während:
dauert 0.005s, und "6 ^ 6 ^ 6" dauert 0.184s, so dass die Potenzierung von bc über 4x langsamer ist als die von Python, obwohl es 7x schneller ist, um anzufangen.
quelle
Ich fand eine schöne Antwort auf SO die verschiedene Felder zu erklären:
In Ihrem speziellen Beispiel ist die Python-Version also schneller als die tatsächliche Zeit, die für die Fertigstellung benötigt wird. Der Python-Ansatz verbringt jedoch mehr Zeit im Kernel-Space und ruft Kernelfunktionen auf. Der
bc
Befehl verbringt im Wesentlichen keine Zeit im Kernelraum und seine gesamte Zeit wird im Benutzerraum verbracht, vermutlich um internenbc
Code auszuführen.Das macht für Sie keinen Unterschied. Die einzige Information, die Sie wirklich interessieren
real
, ist die tatsächliche Zeit, die zwischen dem Starten des Befehls und der Ausgabe vergangen ist.Sie sollten sich auch darüber im Klaren sein, dass diese winzigen Unterschiede nicht stabil sind, sondern auch von der Auslastung Ihres Systems abhängen und sich jedes Mal ändern, wenn Sie den Befehl ausführen:
quelle
Ich werde es aus einer anderen Perspektive erklären.
Fairerweise
bc
hat es den Vorteil, dass es nichts von der Festplatte lesen muss und nur seine Blobs / Binärdateien benötigt, während Python eine Reihe von Modulen importieren und eine Datei lesen muss. So könnte Ihr Test in Richtung voreingenommen seinbc
. Um es tatsächlich zu testen, sollten Sie verwenden,bc -q file
wofile
enthält:Durch diese Änderung wurde die Verwendungsdauer geändert
echo
:So verwenden Sie die Datei:
(Sie müssen die Methode von Terdon anwenden, um größere Unterschiede festzustellen, aber zumindest wissen wir, dass dies der Fall ist.)
Aus Sicht von Python muss Python jetzt jedes Mal, wenn die Datei geladen wird, von der Festplatte lesen, kompilieren und ausführen sowie Module als Andrew-Punkte laden , was die Ausführungszeit verlangsamt. Wenn Sie den Bytecode des Python-Skripts kompilieren, werden Sie feststellen, dass die Gesamtzeit für die Ausführung des Codes um 50% verkürzt wird:
zusammengestellt:
Wie Sie sehen, gibt es mehrere Faktoren, die die zeitliche Ausführung zwischen verschiedenen Tools beeinflussen können.
quelle
Ich hatte den Vorteil, die anderen Antworten zu lesen. Für den Anfang sollten Leute wie ich wissen, warum wir es hier mit einer so großen Ganzzahl zu tun haben, dass beide
Python
undbc
die rechtsassoziative Exponentiation expandieren, was bedeutet, dass dies nicht der Fall ist6^36
wir die Bewertung , sondern6^46656
die wesentlich größer ist . 1Mit Variationen der folgenden Befehle können wir einen Durchschnitt für ein bestimmtes Element der Ausgabe von beiden extrahieren
time
reservierten Worts als auch des Befehls :Es ist möglich, eine andere Route zu wählen und die Datei vollständig aus dem Vergleich zu entfernen. Außerdem können wir das Timing von bc historisch mit dem
dc
Befehl vergleichen ersterer ein "Front-End-Prozessor" für letzteren ist. Die folgenden Befehle wurden zeitgesteuert:Beachten Sie, dass der
dc
Befehl für die Potenzierung linksassoziativ ist.2Wir haben einige Ergebnisse mit
time
(bash) für 1000 Iterationen (in Sekunden):bc
unddc
bieten in diesem Zusammenhang eine vergleichbare Leistung.Weniger genau 3 ergibt sich aus
/usr/bin/time
zB GNUtime
Befehl (Skalengenauigkeit ist hier nicht gültig, aber die Ergebnisse sind ähnlich):Ein Vorteil von
/usr/bin/time
ist, dass es die-v
Option bietet, die viel mehr Informationen liefert, die schließlich nützlich sein könnten.Es ist auch möglich, dies intern sozusagen mit dem
timeit
Python-Modul auszuwerten :Das ist etwas schneller als das, was wir vorher gesehen haben. Lassen Sie uns den Interpreter selbst ausprobieren:
Das ist das Schnellste, was ich gesehen habe.
Wenn wir eine geringere Exponentiation wie auswerten
6^6
, liefert der Befehl time überraschende Ergebnisse - unter Verwendung der gleichenfor
Schleifenbefehle, die wir jetzt verwendet haben:Also mit einer kleineren ganzen Zahl
bc
ist das plötzlich viel schneller ?? Vom Systemneustart bis zum zweiten Durchlauf macht es keinen Unterschied. Gleichzeitig erhalten wir, wenn wirtimeit
für Python verwenden, Folgendes:Dies ist Mikrosekunden , nicht Millisekunden, und entspricht nicht den viel langsameren Ergebnissen, die mit der
for
Schleife erzielt werden . Möglicherweise sind andere Tools erforderlich, um dies weiter zu testen, und wie andere bereits erklärt haben, gibt es hier mehr, als man auf den ersten Blick sieht. Es scheint, dass Python im Szenario der Frage schneller war, aber es ist nicht klar, ob darüber hinaus Schlussfolgerungen gezogen werden können ...1. Unnötig zu erwähnen, dass es über den Rahmen der arithmetischen Erweiterung von Echo hinausgeht, dh
echo $((6**6**6))
-bash
auch dafür ist es zufällig rechtsassoziativ, dh6^6^6 = 6^(6^6)
.2. Vergleichen Sie mit diesem:
6 6 ^ 6 ^ p
.3. Es ist möglich, dass der GNU-Zeitbefehl weitere Informationen liefert, wenn er unter BSD UNIX ausgeführt wird (GNU-Zeitinformationsdokument): Die meisten von 'time' angezeigten Informationen stammen aus dem Systemaufruf 'wait3'. Die Zahlen sind nur so gut wie die von 'wait3' zurückgegebenen. Viele Systeme messen nicht alle Ressourcen, über die "Zeit" berichten kann. Diese Ressourcen werden als Null gemeldet. Die Systeme, die die meisten oder alle Ressourcen messen, basieren auf 4.2 oder 4.3BSD. Spätere BSD-Versionen verwenden einen anderen Speicherverwaltungscode, der weniger Ressourcen misst. - Auf Systemen, die keinen 'wait3'-Aufruf haben, der Statusinformationen zurückgibt, wird stattdessen der' times'-Systemaufruf verwendet. Es liefert viel weniger Informationen als 'wait3', so dass 'time' auf diesen Systemen die meisten Ressourcen als Null anzeigt.
quelle