Dies war eine Interviewfrage, die von einem Senior Manager gestellt wurde.
Welche ist schneller?
while(1) {
// Some code
}
oder
while(2) {
//Some code
}
Ich sagte, dass beide die gleiche Ausführungsgeschwindigkeit haben, da der Ausdruck im Inneren while
schließlich zu true
oder ausgewertet werden sollte false
. In diesem Fall bewerten beide true
und es gibt keine zusätzlichen bedingten Anweisungen innerhalb der while
Bedingung. Beide haben also die gleiche Ausführungsgeschwindigkeit und ich bevorzuge while (1).
Aber der Interviewer sagte zuversichtlich: "Überprüfen Sie Ihre Grundlagen. Ist while(1)
schneller als while(2)
." (Er hat mein Vertrauen nicht auf die Probe gestellt)
Ist das wahr?
Siehe auch: Ist "for (;;)" schneller als "while (TRUE)"? Wenn nicht, warum benutzen die Leute es?
c
performance
while-loop
Nikole
quelle
quelle
0x100000f90: jmp 0x100000f90
für beide Snippets bringt (die Adresse variiert offensichtlich) . Der Interviewer hat sich wahrscheinlich gegen einen Registertest gegen einen einfachen markierten Sprung abgesichert. Sowohl die Frage als auch ihre Vermutung sind lahm.Antworten:
Beide Schleifen sind unendlich, aber wir können sehen, welche mehr Anweisungen / Ressourcen pro Iteration benötigt.
Mit gcc habe ich die beiden folgenden Programme für die Montage auf verschiedenen Optimierungsstufen kompiliert:
Auch ohne Optimierungen (
-O0
) war die generierte Assembly für beide Programme identisch . Daher gibt es keinen Geschwindigkeitsunterschied zwischen den beiden Schleifen.Als Referenz ist hier die generierte Assembly (unter Verwendung
gcc main.c -S -masm=intel
eines Optimierungsflags):Mit
-O0
:Mit
-O1
:Mit
-O2
und-O3
(gleiche Ausgabe):Tatsächlich ist die für die Schleife generierte Baugruppe für jede Optimierungsstufe identisch:
Die wichtigen Punkte sind:
Ich kann Assembly nicht sehr gut lesen, aber dies ist offensichtlich eine bedingungslose Schleife. Die
jmp
Anweisung setzt das Programm bedingungslos auf das.L2
Label zurück, ohne einen Wert mit true zu vergleichen, und tut dies natürlich sofort wieder, bis das Programm irgendwie beendet ist. Dies entspricht direkt dem C / C ++ - Code:Bearbeiten:
Interessanterweise erzeugten die folgenden Schleifen auch ohne Optimierungen
jmp
in der Montage genau dieselbe Ausgabe (bedingungslos ):Und sogar zu meinem Erstaunen:
Mit benutzerdefinierten Funktionen wird es etwas interessanter:
Bei
-O0
diesen beiden Beispielen wird tatsächlichx
ein Vergleich für jede Iteration aufgerufen und durchgeführt.Erstes Beispiel (Rückgabe 1):
Zweites Beispiel (Rückkehr
sqrt(7)
):Bei
-O1
und darüber produzieren beide jedoch dieselbe Baugruppe wie die vorherigen Beispiele (eine bedingungslosejmp
Rückkehr zum vorhergehenden Etikett).TL; DR
Unter GCC werden die verschiedenen Schleifen zu identischen Baugruppen kompiliert. Der Compiler wertet die konstanten Werte aus und führt keinen tatsächlichen Vergleich durch.
Die Moral der Geschichte lautet:
quelle
-O
Ebene die gleiche Baugruppe .jmp
zurück zum Anfang oder die Schleife vollständig entfernen.break
Anweisungen), aber ich habe es trotzdem getestet und nein, selbst mit Code innerhalb der Schleife ist der Sprung absolut und bedingungslos für beidewhile(1)
undwhile(2)
. Fühlen Sie sich frei, die anderen selbst zu testen, wenn Sie tatsächlich besorgt sind.Ja,
while(1)
ist viel schneller alswhile(2)
, für einen Menschen zu lesen! Wenn ichwhile(1)
in einer unbekannten Codebasis sehe, weiß ich sofort, was der Autor beabsichtigt hat, und meine Augäpfel können mit der nächsten Zeile fortfahren.Wenn ich sehe
while(2)
, werde ich wahrscheinlich in meinen Spuren stehen bleiben und versuchen herauszufinden, warum der Autor nicht geschrieben hatwhile(1)
. Ist der Finger des Autors auf der Tastatur gerutscht? Verwenden die Betreuer dieser Codebasiswhile(n)
einen obskuren Kommentierungsmechanismus, um Schleifen anders aussehen zu lassen? Ist es eine grobe Problemumgehung für eine falsche Warnung in einem defekten statischen Analysewerkzeug? Oder ist dies ein Hinweis darauf, dass ich generierten Code lese? Ist es ein Fehler, der aus einem schlecht beratenen Finden und Ersetzen aller oder einer schlechten Verschmelzung oder einem kosmischen Strahl resultiert? Vielleicht soll diese Codezeile etwas dramatisch anderes bewirken. Vielleicht sollte es lesenwhile(w)
oderwhile(x2)
. Ich finde den Autor besser im Verlauf der Datei und sende ihnen eine "WTF" -E-Mail ... und jetzt habe ich meinen mentalen Kontext gebrochen.while(2)
while(1)
hätte einen Bruchteil einer Sekunde gedauert!Ich übertreibe, aber nur ein bisschen. Die Lesbarkeit des Codes ist wirklich wichtig. Und das ist in einem Interview erwähnenswert!
quelle
svn-annotate
odergit blame
(oder was auch immer) verwendet, und im Allgemeinen dauert es Minuten, um einen Datei-Schuldverlauf zu laden. Dann, nur um endlich zu entscheiden, "ah, ich verstehe, der Autor hat diese Zeile geschrieben, als er frisch von der Highschool war", verlor gerade 10 Minuten ...1
.while(2)
im Code sah (bis hin zur Überlegung: "Verwenden die Betreuer dieser Codebasis while (n) als obskuren Kommentierungsmechanismus, um Schleifen anders aussehen zu lassen?" ). Also nein, du übertreibst nicht!Die vorhandenen Antworten, die den von einem bestimmten Compiler für ein bestimmtes Ziel mit einem bestimmten Satz von Optionen generierten Code anzeigen, beantworten die Frage nicht vollständig - es sei denn, die Frage wurde in diesem bestimmten Kontext gestellt ("Was mit gcc 4.7.2 für x86_64 schneller ist mit Standardoptionen? ", zum Beispiel).
In Bezug auf die Sprachdefinition wertet die abstrakte Maschine in der abstrakten Maschine
while (1)
die Ganzzahlkonstante1
undwhile (2)
die Ganzzahlkonstante aus2
; In beiden Fällen wird das Ergebnis auf Gleichheit mit Null verglichen. Der Sprachstandard sagt absolut nichts über die relative Leistung der beiden Konstrukte aus.Ich kann mir vorstellen, dass ein extrem naiver Compiler möglicherweise unterschiedlichen Maschinencode für die beiden Formulare generiert, zumindest wenn er kompiliert wird, ohne eine Optimierung anzufordern.
Andererseits müssen C-Compiler zur Kompilierungszeit unbedingt einige konstante Ausdrücke auswerten , wenn sie in Kontexten erscheinen, die einen konstanten Ausdruck erfordern. Zum Beispiel:
erfordert eine Diagnose; Ein fauler Compiler hat nicht die Möglichkeit, die Auswertung
2+2
bis zur Ausführungszeit zu verschieben. Da ein Compiler die Fähigkeit haben muss, konstante Ausdrücke zur Kompilierungszeit auszuwerten, gibt es keinen guten Grund, diese Fähigkeit nicht zu nutzen, selbst wenn sie nicht benötigt wird.Der C-Standard ( N1570 6.8.5p4) besagt dies
Die relevanten konstanten Ausdrücke sind also
1 == 0
und2 == 0
, die beide denint
Wert ergeben0
. (Dieser Vergleich ist implizit in der Semantik derwhile
Schleife enthalten; sie existieren nicht als tatsächliche C-Ausdrücke.)Ein pervers naiver Compiler könnte unterschiedlichen Code für die beiden Konstrukte generieren. Zum einen könnte es zum einen eine bedingungslose Endlosschleife erzeugen (
1
als Sonderfall behandeln ), und zum anderen könnte es einen expliziten Laufzeitvergleich erzeugen, der äquivalent zu ist2 != 0
. Aber ich bin noch nie auf einen C-Compiler gestoßen, der sich tatsächlich so verhält, und ich bezweifle ernsthaft, dass es einen solchen Compiler gibt.Die meisten Compiler (ich bin versucht zu sagen, dass alle Compiler in Produktionsqualität) haben Optionen, um zusätzliche Optimierungen anzufordern. Bei einer solchen Option ist es noch weniger wahrscheinlich, dass ein Compiler unterschiedlichen Code für die beiden Formulare generiert.
Wenn Ihr Compiler für die beiden Konstrukte unterschiedlichen Code generiert, überprüfen Sie zunächst, ob die unterschiedlichen Codesequenzen tatsächlich eine unterschiedliche Leistung aufweisen. Versuchen Sie in diesem Fall erneut, mit einer Optimierungsoption zu kompilieren (falls verfügbar). Wenn sie sich immer noch unterscheiden, senden Sie einen Fehlerbericht an den Compilerhersteller. Es ist nicht (notwendigerweise) ein Fehler im Sinne einer Nichteinhaltung des C-Standards, aber es ist mit ziemlicher Sicherheit ein Problem, das behoben werden sollte.
Fazit:
while (1)
und mitwhile(2)
ziemlicher Sicherheit die gleiche Leistung haben. Sie haben genau die gleiche Semantik, und es gibt keinen guten Grund für einen Compiler, keinen identischen Code zu generieren.Und obwohl es für einen Compiler völlig legal ist, schnelleren Code für
while(1)
als für zu generierenwhile(2)
, ist es für einen Compiler ebenso legal, schnelleren Code fürwhile(1)
als für ein anderes Vorkommenwhile(1)
im selben Programm zu generieren .(In der von Ihnen gestellten Frage ist eine weitere Frage enthalten: Wie gehen Sie mit einem Interviewer um, der auf einem falschen technischen Punkt besteht. Dies wäre wahrscheinlich eine gute Frage für die Workplace-Site. )
quelle
while
vom Skalartyp sein muss und der Schleifenkörper wiederholt wird, bis der Ausdruck gleich 0 ist. Er sagt nicht, dass es ein Implizit gibtexpr != 0
, das ausgewertet wird ... das das Ergebnis von erfordern würde dass - 0 oder 1 - wiederum ad infinitum mit 0 verglichen werden. Nein, der Ausdruck wird mit 0 verglichen, aber dieser Vergleich ergibt keinen Wert. PS Ich habe gestimmt.<expr> == 0
; Das ist es, was "Vergleiche gleich 0" in C bedeutet . Dieser Vergleich ist Teil der Semantik derwhile
Schleife. Weder im Standard noch in meiner Antwort gibt es eine Implikation, dass das Ergebnis erneut verglichen0
werden muss. (Ich hätte eher schreiben sollen==
als!=
.) Aber dieser Teil meiner Antwort war unklar und ich werde ihn aktualisieren.while (2)
,while (pointer)
,while (9.67)
, durch die naiven, nicht optimieren Compiler, werden Sie keinen Code sehen erzeugt , dass die Renditen0
oder1
. "Ich hätte == schreiben sollen anstatt! =" - nein, das hätte keinen Sinn ergeben.... == 0
C-Ausdrucks impliziert . Mein Punkt ist, dass sowohl die "Vergleiche gleich 0", die für die Beschreibung derwhile
Schleifen durch den Standard erforderlich sind, als auch ein expliziterx == 0
Ausdruck logisch dieselbe Operation implizieren. Und ich denke, dass ein schmerzlich naiver C-Compiler Code generieren könnte, der einenint
Wert von0
oder1
für einewhile
Schleife generiert - obwohl ich nicht glaube, dass ein tatsächlicher Compiler so naiv ist.Warte eine Minute. Der Interviewer, sah er aus wie dieser Typ?
Es ist schon schlimm genug, dass der Interviewer selbst dieses Interview nicht bestanden hat. Was ist, wenn andere Programmierer dieser Firma diesen Test "bestanden" haben?
Bewertung der Aussagen
1 == 0
und2 == 0
sollte gleich schnell sein. Wir könnten uns schlechte Compiler-Implementierungen vorstellen , bei denen eine schneller als die andere sein könnte. Aber es gibt keinen guten Grund, warum einer schneller sein sollte als der andere.Selbst wenn es einen obskuren Umstand gibt, unter dem die Behauptung wahr wäre, sollten Programmierer nicht auf der Grundlage des Wissens über obskure (und in diesem Fall gruselige) Trivia bewertet werden. Mach dir keine Sorgen um dieses Interview, der beste Schritt hier ist, wegzugehen.
Haftungsausschluss: Dies ist KEIN Original-Dilbert-Cartoon. Dies ist nur ein Mashup .
quelle
cmp
Operand in weniger Zyklen ausgeführt, wenn 1 zu 0 verglichen wird, als 2 zu 0? Wie viele Zyklen dauert es, um cmp im Allgemeinen auszuführen? ist es variabel nach Bitmustern? Sind sie "komplexere" Bitmuster, die langsamer werdencmp
? Ich weiß es nicht persönlich. Sie können sich eine super idiotische Implementierung vorstellen, die Stück für Stück von Rang 0 bis n prüft (z. B. n = 31).cmp
Operand sollte für 1 und 200 gleich schnell sein. Wahrscheinlich könnten wir uns idiotische Implementierungen vorstellen , bei denen dies nicht der Fall ist. Aber können wir uns eine nicht-idiotische Implementierung vorstellen , bei derwhile(1)
es schneller geht alswhile(200)
? Wenn in einem prähistorischen Zeitalter die einzige verfügbare Implementierung so idiotisch war, sollten wir uns heute darüber aufregen? Ich glaube nicht, das ist ein spitzes Chefgespräch und ein echtes Juwel!Ihre Erklärung ist richtig. Dies scheint eine Frage zu sein, die neben technischem Wissen auch Ihr Selbstvertrauen auf die Probe stellt.
Übrigens, wenn Sie geantwortet haben
der Interviewer würde sagen
Wenn Sie also wie Sie geantwortet haben, haben Sie einige Zeit gespart, die Sie sonst für die Diskussion dieser schlechten Frage verschwenden würden.
Hier ist ein Beispielcode, der vom Compiler auf meinem System (MS Visual Studio 2012) mit deaktivierten Optimierungen generiert wurde:
Mit aktivierten Optimierungen:
Der generierte Code ist also genau der gleiche, zumindest mit einem optimierenden Compiler.
quelle
while
lange davor) und der Operand vonwhile
ist nicht vom booleschen oder _Bool oder einem anderen bestimmten Typ. Der Operand vonwhile
kann ein beliebiger Ausdruck sein ... während while auf 0 bricht und auf Nicht-0 fortgesetzt wird.while (00000001) {}
inwhile (00000000) {}
. Je mehr wahre Bits Sie haben, desto geringer ist die Wahrscheinlichkeit, dass der Wert auf falsch wechselt. Leider hat 2 auch nur ein wahres Bit. 3 würde jedoch deutlich länger laufen. Dies gilt auch nur für einen Compiler, der dies nicht immer optimiert (VC ++).Die wahrscheinlichste Erklärung für die Frage ist, dass der Interviewer denkt, dass der Prozessor die einzelnen Bits der Zahlen nacheinander überprüft, bis sie einen Wert ungleich Null erreichen:
Wenn das "Null ist?" Der Algorithmus beginnt auf der rechten Seite der Zahl und muss jedes Bit prüfen, bis es ein Bit ungleich Null erreicht. Die
while(1) { }
Schleife müsste doppelt so viele Bits pro Iteration prüfen wie diewhile(2) { }
Schleife.Dies erfordert ein sehr falsches mentales Modell der Funktionsweise von Computern, hat jedoch eine eigene interne Logik. Eine Möglichkeit zur Kontrolle wäre, wenn zu fragen ,
while(-1) { }
oderwhile(3) { }
würde gleich schnell sein, oder wennwhile(32) { }
sei sogar noch langsamer .quelle
cmp
Algorithmus einer CPU im Grunde genommen eine lineare Bitprüfung mit frühem Schleifenausgang bei der ersten Differenz ist.-O0
Ausgabe von gcc oder clang nicht wörtlich genug ist." Ich habe so etwas nie gesagt und ich hatte überhaupt kein gcc oder clang im Sinn. Du musst mich falsch verstanden haben. Ich bin einfach nicht der Meinung, dass das, was MSVC produziert, lustig ist.while(1)
nicht vor der Schleife, sondern auf dem Ausdruck. Es kollabiert jedoch immer noch innerhalb der Schleife, wenn der Ausdruck entfernt wird. Nehmen Sie diesen Code mit vielen Pausen. Im nicht optimierten Debugging-Modus erhalten Sie dies . Bei der Optimierung fallen viele Haltepunkte zusammen oder gehen sogar in die nächste Funktion über (die IDE zeigt die Ergebnis-Haltepunkte beim Debuggen an) - entsprechende Demontage .Natürlich kenne ich die wahren Absichten dieses Managers nicht, aber ich schlage eine völlig andere Sichtweise vor: Wenn Sie ein neues Mitglied in ein Team einstellen, ist es hilfreich zu wissen, wie es auf Konfliktsituationen reagiert.
Sie haben dich in einen Konflikt getrieben. Wenn dies wahr ist, sind sie klug und die Frage war gut. Für einige Branchen wie das Bankwesen kann das Posten Ihres Problems in Stack Overflow ein Grund für die Ablehnung sein.
Aber natürlich weiß ich nicht, ich schlage nur eine Option vor.
quelle
Ich denke, der Hinweis liegt in "von einem Senior Manager gefragt". Diese Person hat offensichtlich aufgehört zu programmieren, als sie Manager wurde, und dann hat sie mehrere Jahre gebraucht, um Senior Manager zu werden. Nie das Interesse an Programmierung verloren, aber seit diesen Tagen nie mehr eine Zeile geschrieben. Seine Referenz ist also nicht "irgendein anständiger Compiler da draußen", wie einige Antworten erwähnen, sondern "der Compiler, mit dem diese Person vor 20 bis 30 Jahren zusammengearbeitet hat".
Zu dieser Zeit verbrachten Programmierer einen beträchtlichen Prozentsatz ihrer Zeit damit, verschiedene Methoden auszuprobieren, um ihren Code schneller und effizienter zu machen, da die CPU-Zeit des „zentralen Minicomputers“ so wertvoll war. Wie die Leute, die Compiler schreiben. Ich vermute, dass der einzige Compiler, den sein Unternehmen zu diesem Zeitpunkt zur Verfügung stellte, auf der Grundlage von "häufig angetroffenen Aussagen, die optimiert werden können" optimiert wurde und bei einer Weile eine Abkürzung nahm (1) und alles auswertete sonst, einschließlich einer Weile (2). Eine solche Erfahrung gemacht zu haben, könnte seine Position und sein Vertrauen in sie erklären.
Der beste Ansatz, um Sie einzustellen, ist wahrscheinlich einer, der es dem Senior Manager ermöglicht, sich mitreißen zu lassen und Sie 2-3 Minuten über "die guten alten Tage des Programmierens" zu unterrichten, bevor SIE ihn reibungslos zum nächsten Interviewthema führen. (Gutes Timing ist hier wichtig - zu schnell und Sie unterbrechen die Geschichte - zu langsam und Sie werden als jemand mit unzureichendem Fokus bezeichnet). Sagen Sie ihm am Ende des Interviews, dass Sie sehr daran interessiert wären, mehr über dieses Thema zu erfahren.
quelle
Sie hätten ihn fragen sollen, wie er zu diesem Schluss gekommen ist. Unter jedem anständigen Compiler da draußen kompilieren die beiden nach denselben asm-Anweisungen. Also hätte er dir auch sagen sollen, dass der Compiler anfangen soll. Und trotzdem müsste man den Compiler und die Plattform sehr gut kennen, um überhaupt eine theoretisch fundierte Vermutung anstellen zu können. Und am Ende spielt es in der Praxis keine Rolle, da andere externe Faktoren wie Speicherfragmentierung oder Systemlast die Schleife stärker beeinflussen als dieses Detail.
quelle
Um dieser Frage willen sollte ich hinzufügen, dass ich mich daran erinnere, dass Doug Gwyn vom C-Komitee schrieb, dass einige frühe C-Compiler ohne den Optimierungsdurchlauf einen Assembler-Test für das generieren würden
while(1)
(im Vergleich zufor(;;)
dem, der es nicht hätte).Ich würde dem Interviewer mit dieser historischen Notiz antworten und dann sagen, dass selbst wenn ich sehr überrascht wäre, dass ein Compiler dies getan hat, ein Compiler Folgendes haben könnte:
while(1)
undwhile(2)
while(1)
da sie als idiomatisch angesehen werden. Dies würde daswhile(2)
mit einem Test belassen und macht daher einen Leistungsunterschied zwischen den beiden.Ich möchte dem Interviewer natürlich hinzufügen, dass das Nicht-Berücksichtigen
while(1)
undwhile(2)
das gleiche Konstrukt ein Zeichen für eine Optimierung von geringer Qualität ist, da dies äquivalente Konstrukte sind.quelle
Eine andere Möglichkeit, eine solche Frage zu beantworten, wäre zu sehen, ob Sie den Mut haben, Ihrem Manager zu sagen, dass er / sie falsch liegt! Und wie leise Sie es kommunizieren können.
Mein erster Instinkt wäre gewesen, eine Assembly-Ausgabe zu generieren, um dem Manager zu zeigen, dass jeder anständige Compiler sich darum kümmern sollte, und wenn dies nicht der Fall ist, werden Sie den nächsten Patch dafür einreichen :)
quelle
Um zu sehen, wie sich so viele Menschen mit diesem Problem befassen, wird genau gezeigt, warum dies ein Test sein kann, um festzustellen, wie schnell Sie die Dinge mikrooptimieren möchten .
Meine Antwort wäre; es ist nicht so wichtig, ich konzentriere mich eher auf das Geschäftsproblem, das wir lösen. Schließlich werde ich dafür bezahlt.
Außerdem würde ich mich dafür entscheiden,
while(1) {}
weil es häufiger vorkommt und andere Teamkollegen keine Zeit aufwenden müssten, um herauszufinden, warum sich jemand für eine höhere Zahl als 1 entscheiden würde.Schreiben Sie jetzt einen Code. ;-);
quelle
Wenn Sie sich Sorgen um die Optimierung machen, sollten Sie diese verwenden
denn das hat keine tests. (zynischer Modus)
quelle
while(2)
, es lässt Raum für Optimierungen, und Sie wechseln einfach zu,for (;;)
wenn Sie für eine Leistungssteigerung bereit sind.Es scheint mir, dass dies eine dieser Verhaltensinterviewfragen ist, die als technische Frage maskiert sind. Einige Unternehmen tun dies - sie stellen eine technische Frage, die für jeden kompetenten Programmierer relativ einfach zu beantworten sein sollte. Wenn der Befragte jedoch die richtige Antwort gibt, teilt der Interviewer ihnen mit, dass sie falsch liegen.
Das Unternehmen möchte sehen, wie Sie in dieser Situation reagieren werden. Sitzen Sie ruhig da und drängen Sie nicht darauf, dass Ihre Antwort richtig ist, entweder aus Selbstzweifeln oder aus Angst, den Interviewer zu verärgern? Oder sind Sie bereit, eine autoritäre Person herauszufordern, von der Sie wissen, dass sie falsch ist? Sie wollen sehen, ob Sie bereit sind, für Ihre Überzeugungen einzutreten, und ob Sie dies taktvoll und respektvoll tun können.
quelle
Früher habe ich C- und Assembly-Code zurückprogrammiert, wenn diese Art von Unsinn einen Unterschied gemacht haben könnte. Als es einen Unterschied machte, haben wir es in Assembly geschrieben.
Wenn mir diese Frage gestellt worden wäre, hätte ich Donald Knuths berühmtes Zitat von 1974 über vorzeitige Optimierung wiederholt und wäre gegangen, wenn der Interviewer nicht gelacht und weitergemacht hätte.
quelle
Vielleicht hat der Interviewer absichtlich eine so dumme Frage gestellt und wollte, dass Sie 3 Punkte machen:
quelle
Hier ist ein Problem: Wenn Sie tatsächlich ein Programm schreiben und dessen Geschwindigkeit messen, kann die Geschwindigkeit beider Schleifen unterschiedlich sein! Für einen vernünftigen Vergleich:
Wenn ein Code hinzugefügt wird, der die Zeit druckt, kann ein zufälliger Effekt wie die Positionierung der Schleife innerhalb einer oder zweier Cache-Zeilen einen Unterschied bewirken. Eine Schleife kann sich zufällig vollständig innerhalb einer Cache-Zeile oder am Anfang einer Cache-Zeile befinden oder zwei Cache-Zeilen überspannen. Infolgedessen könnte alles, was der Interviewer für am schnellsten hält, tatsächlich am schnellsten sein - zufällig.
Worst-Case-Szenario: Ein optimierender Compiler findet nicht heraus, was die Schleife tut, stellt jedoch fest, dass die Werte, die bei der Ausführung der zweiten Schleife erzeugt werden, dieselben sind wie die der ersten. Und generieren Sie vollständigen Code für die erste Schleife, aber nicht für die zweite.
quelle
Sie sind beide gleich - gleich.
Gemäß den Spezifikationen wird alles, was nicht 0 ist, als wahr angesehen, also auch ohne Optimierung, und ein guter Compiler generiert keinen Code für while (1) oder while (2). Der Compiler würde eine einfache Prüfung für generieren
!= 0
.quelle
Gemessen an der Zeit und Mühe, die die Leute damit verbracht haben, diese sehr einfache Frage zu testen, zu beweisen und zu beantworten, würde ich sagen, dass beide durch das Stellen der Frage sehr langsam gemacht wurden.
Und um noch mehr Zeit damit zu verbringen ...
"while (2)" ist lächerlich, weil,
"while (1)" und "while (true)" werden historisch verwendet, um eine Endlosschleife zu erstellen, die erwartet, dass "break" irgendwann innerhalb der Schleife aufgerufen wird, basierend auf einer Bedingung, die sicherlich auftreten wird.
Die "1" ist einfach da, um immer als wahr zu bewerten, und daher ist "während (2)" ungefähr so albern wie "während (1 + 1 == 2)" zu sagen, was ebenfalls als wahr bewertet wird.
Und wenn Sie völlig albern sein wollen, verwenden Sie einfach: -
Ich würde gerne glauben, dass Ihr Codierer einen Tippfehler gemacht hat, der die Ausführung des Codes nicht beeinflusst hat. Wenn er jedoch absichtlich die "2" verwendet hat, um seltsam zu sein, entlassen Sie ihn, bevor er seltsame Dinge durch Ihren Code steckt, was es schwierig macht lesen und arbeiten mit.
quelle
Das hängt vom Compiler ab.
Wenn der Code optimiert wird oder wenn 1 und 2 mit der gleichen Anzahl von Befehlen für einen bestimmten Befehlssatz als wahr ausgewertet werden, ist die Ausführungsgeschwindigkeit gleich.
In realen Fällen wird es immer gleich schnell sein, aber es wäre möglich, sich einen bestimmten Compiler und ein bestimmtes System vorzustellen, wenn dies anders bewertet würde.
Ich meine: Dies ist nicht wirklich eine sprachbezogene Frage.
quelle
Da Leute, die diese Frage beantworten möchten, die schnellste Schleife wünschen, hätte ich geantwortet, dass beide gleichermaßen in denselben Assembler-Code kompiliert werden, wie in den anderen Antworten angegeben. Trotzdem können Sie dem Interviewer vorschlagen, "Loop Unrolling" zu verwenden. eine do {} while-Schleife anstelle der while-Schleife.
Vorsicht: Sie müssen sicherstellen, dass die Schleife mindestens immer einmal ausgeführt wird .
Die Schleife sollte innen eine Unterbrechungsbedingung haben.
Auch für diese Art von Schleife würde ich persönlich die Verwendung von do {} while (42) bevorzugen, da jede Ganzzahl außer 0 den Job erledigen würde.
quelle
Die offensichtliche Antwort lautet: Wie veröffentlicht, würden beide Fragmente eine gleichermaßen ausgelastete Endlosschleife ausführen, was das Programm unendlich langsam macht .
Obwohl die Neudefinition von C-Schlüsselwörtern als Makros technisch undefiniertes Verhalten hätte, ist dies die einzige Möglichkeit, eines der Codefragmente überhaupt schnell zu machen: Sie können diese Zeile über den beiden Fragmenten hinzufügen:
es wird in der Tat
while(1)
doppelt so schnell (oder halb so langsam) machen wiewhile(2)
.quelle
Der einzige Grund, warum ich mir vorstellen kann, warum das
while(2)
langsamer sein würde, ist:Der Code optimiert die Schleife auf
cmp eax, 2
Wenn das Subtrahieren auftritt, subtrahieren Sie im Wesentlichen
ein.
00000000 - 00000010 cmp eax, 2
anstatt
b.
00000000 - 00000001 cmp eax, 1
cmp
setzt nur Flags und setzt kein Ergebnis. Auf den niedrigstwertigen Stellen wissen wir also, ob wir mit b ausleihen müssen oder nicht . Während mit a müssen Sie zwei Subtraktionen durchführen, bevor Sie eine Ausleihe erhalten.quelle