Was ist schneller: während (1) oder während (2)?

587

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 whileschließlich zu trueoder ausgewertet werden sollte false. In diesem Fall bewerten beide trueund es gibt keine zusätzlichen bedingten Anweisungen innerhalb der whileBedingung. 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?

Nikole
quelle
202
Ein halbwegs anständiger Compiler optimiert beide Formulare zu nichts.
64
In einem optimierten Build wird (n) jedes Mal n! = 0 oder für (;;) in eine Endlosschleife der Assembly mit Beschriftung am Anfang und gehe am Ende übersetzt. Genau der gleiche Code, die gleiche Leistung.
Alex F
60
Es ist nicht überraschend, dass eine Aktienoptimierung 0x100000f90: jmp 0x100000f90fü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.
WhozCraig
50
Diese Frage des Interviewers fällt unter die gleichen Vorzeichen wie dilbert.com/strips/comic/1995-11-17 - Sie werden jemanden treffen, der wirklich glaubt, was er sagt, unabhängig vom Quotienten der Dummheit in seiner Aussage. Wählen Sie einfach aus den folgenden: eine tiefe Atmung, schwören, lachen, weinen, eine Kombination der oben genannten :)
GMasucci
3
@Mike W: Man kann sich fragen, was ein Compiler tun soll: in eine Halt-Anweisung übersetzen oder bedenken, dass die Schleife nach unendlicher Zeit beendet wird und die unendliche Verzögerung optimiert wird?
Yves Daoust

Antworten:

681

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:

int main(void) {
    while(1) {}
    return 0;
}


int main(void) {
    while(2) {}
    return 0;
}

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=inteleines Optimierungsflags):

Mit -O0:

    .file   "main.c"
    .intel_syntax noprefix
    .def    __main; .scl    2;  .type   32; .endef
    .text
    .globl  main
    .def    main;   .scl    2;  .type   32; .endef
    .seh_proc   main
main:
    push    rbp
    .seh_pushreg    rbp
    mov rbp, rsp
    .seh_setframe   rbp, 0
    sub rsp, 32
    .seh_stackalloc 32
    .seh_endprologue
    call    __main
.L2:
    jmp .L2
    .seh_endproc
    .ident  "GCC: (tdm64-2) 4.8.1"

Mit -O1:

    .file   "main.c"
    .intel_syntax noprefix
    .def    __main; .scl    2;  .type   32; .endef
    .text
    .globl  main
    .def    main;   .scl    2;  .type   32; .endef
    .seh_proc   main
main:
    sub rsp, 40
    .seh_stackalloc 40
    .seh_endprologue
    call    __main
.L2:
    jmp .L2
    .seh_endproc
    .ident  "GCC: (tdm64-2) 4.8.1"

Mit -O2und -O3(gleiche Ausgabe):

    .file   "main.c"
    .intel_syntax noprefix
    .def    __main; .scl    2;  .type   32; .endef
    .section    .text.startup,"x"
    .p2align 4,,15
    .globl  main
    .def    main;   .scl    2;  .type   32; .endef
    .seh_proc   main
main:
    sub rsp, 40
    .seh_stackalloc 40
    .seh_endprologue
    call    __main
.L2:
    jmp .L2
    .seh_endproc
    .ident  "GCC: (tdm64-2) 4.8.1"

Tatsächlich ist die für die Schleife generierte Baugruppe für jede Optimierungsstufe identisch:

 .L2:
    jmp .L2
    .seh_endproc
    .ident  "GCC: (tdm64-2) 4.8.1"

Die wichtigen Punkte sind:

.L2:
    jmp .L2

Ich kann Assembly nicht sehr gut lesen, aber dies ist offensichtlich eine bedingungslose Schleife. Die jmpAnweisung setzt das Programm bedingungslos auf das .L2Label 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:

L2:
    goto L2;

Bearbeiten:

Interessanterweise erzeugten die folgenden Schleifen auch ohne Optimierungenjmp in der Montage genau dieselbe Ausgabe (bedingungslos ):

while(42) {}

while(1==1) {}

while(2==2) {}

while(4<7) {}

while(3==3 && 4==4) {}

while(8-9 < 0) {}

while(4.3 * 3e4 >= 2 << 6) {}

while(-0.1 + 02) {}

Und sogar zu meinem Erstaunen:

#include<math.h>

while(sqrt(7)) {}

while(hypot(3,4)) {}

Mit benutzerdefinierten Funktionen wird es etwas interessanter:

int x(void) {
    return 1;
}

while(x()) {}


#include<math.h>

double x(void) {
    return sqrt(7);
}

while(x()) {}

Bei -O0diesen beiden Beispielen wird tatsächlich xein Vergleich für jede Iteration aufgerufen und durchgeführt.

Erstes Beispiel (Rückgabe 1):

.L4:
    call    x
    testl   %eax, %eax
    jne .L4
    movl    $0, %eax
    addq    $32, %rsp
    popq    %rbp
    ret
    .seh_endproc
    .ident  "GCC: (tdm64-2) 4.8.1"

Zweites Beispiel (Rückkehr sqrt(7)):

.L4:
    call    x
    xorpd   %xmm1, %xmm1
    ucomisd %xmm1, %xmm0
    jp  .L4
    xorpd   %xmm1, %xmm1
    ucomisd %xmm1, %xmm0
    jne .L4
    movl    $0, %eax
    addq    $32, %rsp
    popq    %rbp
    ret
    .seh_endproc
    .ident  "GCC: (tdm64-2) 4.8.1"

Bei -O1und darüber produzieren beide jedoch dieselbe Baugruppe wie die vorherigen Beispiele (eine bedingungslose jmpRü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:

  • Es gibt eine Übersetzungsebene zwischen C ++ - Quellcode und CPU-Anweisungen, und diese Ebene hat wichtige Auswirkungen auf die Leistung.
  • Daher kann die Leistung nicht nur anhand des Quellcodes bewertet werden.
  • Der Compiler sollte intelligent genug sein, um solche trivialen Fälle zu optimieren. Programmierer sollten in den allermeisten Fällen nicht ihre Zeit damit verschwenden, über sie nachzudenken.
Annäherung an DarknessFish
quelle
196
Vielleicht hat der Interviewer gcc nicht benutzt
MM
106
@Matt McNabb Das ist ein guter Punkt, aber wenn sich der Interviewer auf compilerspezifische Optimierungen verlassen hat, muss er dies in seiner Frage sehr explizit angeben und die Antwort "Es gibt keinen Unterschied" als richtig akzeptieren einige (die meisten?) Compiler.
Jonathan Hartley
109
Um jeden Zweifel auszuräumen, habe ich dies in Clang 3.4.2 getestet, und beide Loops erzeugen auf jeder -OEbene die gleiche Baugruppe .
Martin Tournoij
16
Ich finde das überhaupt nicht überraschend, da alles, was Sie in den bedingten Abschnitt der Schleifen eingefügt haben, Konstanten zur Kompilierungszeit sind. Als solches würde ich vermuten, dass ein Compiler sehen würde, dass die Schleifen immer wahr oder falsch sind und entweder einfach jmpzurück zum Anfang oder die Schleife vollständig entfernen.
Sherlellbc
10
@hippietrail Ich sehe nicht, wie der Inhalt (oder das Fehlen hiervon) der Schleife möglicherweise diese Optimierungen beeinflussen könnte (mit Ausnahme der Möglichkeit von breakAnweisungen), aber ich habe es trotzdem getestet und nein, selbst mit Code innerhalb der Schleife ist der Sprung absolut und bedingungslos für beide while(1)und while(2). Fühlen Sie sich frei, die anderen selbst zu testen, wenn Sie tatsächlich besorgt sind.
Annäherung an
282

Ja, while(1)ist viel schneller als while(2), für einen Menschen zu lesen! Wenn ich while(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 hat while(1). Ist der Finger des Autors auf der Tastatur gerutscht? Verwenden die Betreuer dieser Codebasis while(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 lesen while(w)oder while(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!

Chris Culter
quelle
Meine Gedanken genau und genau warum, während (1) schneller ist lol Obwohl ich denke, es war einfach der alte Fall eines Managers, der versuchte, sich selbst davon zu überzeugen, dass er über das Codieren Bescheid weiß, wenn er es nicht tut, wir alle haben es gesehen, jeder möchte ein sein Jedi.
ekerner
8
Absolut, das ist überhaupt keine Übertreibung. Auf jeden Fall wird hier das svn-annotate oder git 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 ...
v.oddou
11
Abgestimmt, weil ich die Konventionen satt habe. Der Entwickler hat diese mickrige Gelegenheit, eine Nummer zu schreiben, die er mag, dann kommt jemand Langweiliges und nörgelt darüber, warum es nicht so ist 1.
Utkan Gezer
1
Aufgrund von Rhetorik herabgestimmt. Das Lesen während (1) entspricht genau der Geschwindigkeit von (2).
hdante
4
Ich habe genau den gleichen mentalen Prozess durchlaufen, wie er in dieser Antwort vor einer Minute beschrieben wurde, als ich ihn 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!
Hisham HM
151

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 Maschinewhile (1) die Ganzzahlkonstante 1und while (2)die Ganzzahlkonstante aus 2; 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:

int n = 4;
switch (n) {
    case 2+2: break;
    case 4:   break;
}

erfordert eine Diagnose; Ein fauler Compiler hat nicht die Möglichkeit, die Auswertung 2+2bis 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

Eine Iterationsanweisung bewirkt, dass eine Anweisung, die als Schleifenkörper bezeichnet wird , wiederholt ausgeführt wird, bis der steuernde Ausdruck gleich 0 ist.

Die relevanten konstanten Ausdrücke sind also 1 == 0und 2 == 0, die beide den intWert ergeben 0. (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 ( 1als Sonderfall behandeln ), und zum anderen könnte es einen expliziten Laufzeitvergleich erzeugen, der äquivalent zu ist 2 != 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 mit while(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 generieren while(2), ist es für einen Compiler ebenso legal, schnelleren Code für while(1)als für ein anderes Vorkommen while(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. )

Keith Thompson
quelle
8
"In diesem Fall sind die relevanten (impliziten) konstanten Ausdrücke 1! = 0 und 2! = 0, die beide den int-Wert 1 ergeben." ... Dies ist zu kompliziert und ungenau. Der Standard sagt einfach, dass der steuernde Ausdruck von whilevom Skalartyp sein muss und der Schleifenkörper wiederholt wird, bis der Ausdruck gleich 0 ist. Er sagt nicht, dass es ein Implizit gibt expr != 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.
Jim Balter
3
@ JimBalter: Ich verstehe Ihren Standpunkt und werde meine Antwort aktualisieren, um ihn anzusprechen. Was ich jedoch meinte, war, dass der Wortlaut des Standards "... bis der steuernde Ausdruck gleich 0 ist" eine Bewertung impliziert <expr> == 0; Das ist es, was "Vergleiche gleich 0" in C bedeutet . Dieser Vergleich ist Teil der Semantik der whileSchleife. Weder im Standard noch in meiner Antwort gibt es eine Implikation, dass das Ergebnis erneut verglichen 0werden muss. (Ich hätte eher schreiben sollen ==als !=.) Aber dieser Teil meiner Antwort war unklar und ich werde ihn aktualisieren.
Keith Thompson
1
"" Vergleiche gleich 0 "bedeutet in C" - aber diese Sprache ist im Standard , nicht in C ... die Implementierung führt den Vergleich durch, es wird kein C-Sprachvergleich generiert. Sie schreiben "beide werden auf den int-Wert 1 ausgewertet" - aber eine solche Auswertung findet nie statt. Wenn Sie den Code anschauen erzeugt für while (2), while (pointer), while (9.67), durch die naiven, nicht optimieren Compiler, werden Sie keinen Code sehen erzeugt , dass die Renditen 0oder 1. "Ich hätte == schreiben sollen anstatt! =" - nein, das hätte keinen Sinn ergeben.
Jim Balter
2
@ JimBalter: Hmmm. Ich will damit nicht sagen, dass "Vergleiche gleich 0" die Existenz eines ... == 0C-Ausdrucks impliziert . Mein Punkt ist, dass sowohl die "Vergleiche gleich 0", die für die Beschreibung der whileSchleifen durch den Standard erforderlich sind, als auch ein expliziter x == 0Ausdruck logisch dieselbe Operation implizieren. Und ich denke, dass ein schmerzlich naiver C-Compiler Code generieren könnte, der einen intWert von 0oder 1für eine whileSchleife generiert - obwohl ich nicht glaube, dass ein tatsächlicher Compiler so naiv ist.
Keith Thompson
12
Hinweis: Dies ist bereits eine The Workplace- Frage: arbeitsplatz.stackexchange.com/questions/4314/…
Joe
141

Warte eine Minute. Der Interviewer, sah er aus wie dieser Typ?

Geben Sie hier die Bildbeschreibung ein

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 == 0und 2 == 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 .

Janos
quelle
6
Das wäre lustig, wenn es auch eine Antwort auf die Frage enthalten würde.
Cody Gray
Nein, aber wirklich, wir können uns alle ziemlich leicht vorstellen, dass alle Compiler, die von seriösen Unternehmen geschrieben wurden, vernünftigen Code produzieren. Nehmen wir den "nicht optimierten Fall" / O0, vielleicht endet er so, wie es Anatolyg gepostet hat. Dann ist es eine Frage der CPU. Wird der cmpOperand 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 werden cmp? 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).
v.oddou
5
Das ist auch mein Punkt: Der cmpOperand 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 der while(1)es schneller geht als while(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!
Janos
@ v.ouddou "Wird der cmp-Operand in weniger Zyklen ausgeführt, wenn 1 zu 0 als 2 zu 0 verglichen wird?" - Nein. Sie sollten lernen, was ein Zyklus ist. "Ich weiß es nicht persönlich. Sie können sich vorstellen, dass eine super idiotische Implementierung Stück für Stück von Rang 0 bis n prüft" - oder umgekehrt, was den Interviewer immer noch zu einem ahnungslosen Idioten macht. Und warum sich Sorgen machen, Stück für Stück zu überprüfen? Die Implementierung könnte ein Mann in einer Box sein, der sich entscheidet, während der Evaluierung Ihres Programms eine Mittagspause einzulegen.
Jim Balter
79

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

Beide Codeteile sind gleich schnell, da beide unendlich lange dauern

der Interviewer würde sagen

Aber while (1)kann mehr Iterationen pro Sekunde tun; kannst du erklären warum? (Das ist Unsinn. Testen Sie Ihr Vertrauen erneut.)

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:

yyy:
    xor eax, eax
    cmp eax, 1     (or 2, depending on your code)
    je xxx
    jmp yyy
xxx:
    ...

Mit aktivierten Optimierungen:

xxx:
    jmp xxx

Der generierte Code ist also genau der gleiche, zumindest mit einem optimierenden Compiler.

Anatolyg
quelle
28
Dieser Code ist wirklich das, was der Compiler auf meinem System ausgibt. Ich habe es nicht erfunden.
Anatolyg
10
Eisbeutel "Der Operand für eine Weile ist vom booleschen Typ" - völliger Unsinn. Bist du der Interviewer? Ich schlage vor, dass Sie sich mit der C-Sprache und ihrem Standard vertraut machen, bevor Sie solche Behauptungen aufstellen.
Jim Balter
29
"Ich habe es nicht erfunden." - Bitte achten Sie nicht auf den Eisbeutel, der Unsinn redet. C hat keinen booleschen Typ (es hat _Bool in stdbool.h, aber das ist nicht dasselbe und die Semantik von whilelange davor) und der Operand von whileist nicht vom booleschen oder _Bool oder einem anderen bestimmten Typ. Der Operand von whilekann ein beliebiger Ausdruck sein ... während while auf 0 bricht und auf Nicht-0 fortgesetzt wird.
Jim Balter
36
"Beide Codeteile sind gleich schnell, da beide unendlich lange dauern", ließ mich an etwas Interessantes denken. Die einzige Möglichkeit, eine Endlosschleife zu beenden, besteht darin, dass ein Bit von einem geladenen Teilchen umgedreht wird oder die Hardware ausfällt: Ändern der Anweisung von while (00000001) {}in while (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 ++).
Jonathan Dickinson
8
@ mr5 nein. Damit ein bisschen Flip tatsächlich zu so etwas führt, sprechen Sie von Ausführungszeiten in Zehntausenden von Jahren. Nur ein Gedankenexperiment. Wenn Sie aus einer unsterblichen Rasse stammen, möchten Sie möglicherweise -1 verwenden, um zu verhindern, dass Bit-Flipping Ihr Programm beeinflusst.
Jonathan Dickinson
60

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:

1 = 00000001
2 = 00000010

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 die while(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) { }oder while(3) { }würde gleich schnell sein, oder wenn while(32) { }sei sogar noch langsamer .

Ryan Cavanaugh
quelle
39
Ich nahm an, dass das Missverständnis des Interviewers eher wie "2 ist ein int, das in einen Booleschen Wert konvertiert werden muss, um in einem bedingten Ausdruck verwendet zu werden, während 1 bereits ein Boolescher Wert ist."
Russell Borogove
7
Und wenn der Vergleichsalgorithmus von links beginnt, ist es umgekehrt.
Paŭlo Ebermann
1
+1, genau das habe ich mir gedacht. Sie können sich gut vorstellen, dass jemand glaubt, dass der cmpAlgorithmus einer CPU im Grunde genommen eine lineare Bitprüfung mit frühem Schleifenausgang bei der ersten Differenz ist.
v.oddou
1
@PeterCordes "Ich habe noch nie jemanden (außer Ihnen) argumentieren hören, dass die -O0Ausgabe 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.
Blubberdiblub
1
@PeterCordes Ich habe mich geirrt, in MSVC bricht ein Haltepunkt auf dem 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 .
Blubberdiblub
32

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.

Tõnu Samuel
quelle
Es ist in der Tat ausgezeichnet, aber while (2) vs while (1) stammt offensichtlich aus Dilbert-Comics. Es kann NICHT von jemandem erfunden werden, der bei klarem Verstand ist (wie kommt jemand auf while (2) als mögliche Schreibweise?). Wenn Ihre Hypothese wahr wäre, würden Sie definitiv ein Problem angeben, das so einzigartig ist, dass Sie es googeln können. Wie "ist while (0xf00b442) langsamer als while (1)", wie würde die Bank die Frage des Befragten sonst finden? Nehmen Sie an, sie sind die NSA und haben Zugriff auf Keyscore?
v.oddou
25

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.

OldFrank
quelle
19

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.

Valentin Radu
quelle
14
@GKFX Wenn Sie Ihre Antwort gegeben haben und sie Ihnen sagen, dass Sie falsch liegen, gibt es keinen Grund, warum Sie sie nicht bitten können, zu erklären, warum. Wenn Anatolyg richtig ist und es ein Test für Ihr Selbstvertrauen ist, sollten Sie erklären, warum Sie so geantwortet haben, wie Sie es getan haben, und sie gleich fragen.
P. Turpie
Ich meinte als erstes, was du ihnen sagst. Es kann nicht "Warum ist x schneller?" Sein. "Ich weiß nicht; warum ist x schneller?". Nachdem Sie richtig geantwortet haben, können Sie natürlich fragen.
GKFX
18

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 zu for(;;)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:

  • Ohne Optimierer-Pass generiert der Compiler einen Test für beide while(1)undwhile(2)
  • Mit Optimizer Pass wird der Compiler angewiesen, alle zu optimieren (mit einem bedingungslosen Sprung), while(1)da sie als idiomatisch angesehen werden. Dies würde das while(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)und while(2)das gleiche Konstrukt ein Zeichen für eine Optimierung von geringer Qualität ist, da dies äquivalente Konstrukte sind.

ouah
quelle
10

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 :)

OnkelKing
quelle
8

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. ;-);

Bart Verkoeijen
quelle
1
Es sei denn, Sie werden dafür bezahlt, einen Echtzeitcode zu optimieren, für den Sie nur 1 oder 2 Millisekunden rasieren müssen, um die Laufzeitanforderungen zu erfüllen. Natürlich ist das eine Aufgabe für den Optimierer, würden einige sagen - wenn Sie einen Optimierer für Ihre Architektur haben.
Neowizard
6

Wenn Sie sich Sorgen um die Optimierung machen, sollten Sie diese verwenden

for (;;)

denn das hat keine tests. (zynischer Modus)

Tom Tanner
quelle
2
Aus diesem Grund ist es ratsam zu verwenden while(2), es lässt Raum für Optimierungen, und Sie wechseln einfach zu, for (;;)wenn Sie für eine Leistungssteigerung bereit sind.
Groo
5

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.

Pacoverflow
quelle
3

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.

Peter Wooster
quelle
1
Angesichts der Tatsache, dass er sagte: "In etablierten Ingenieurdisziplinen wird eine leicht zu erreichende Verbesserung von 12% niemals als marginal angesehen, und ich glaube, dass der gleiche Standpunkt in der Softwareentwicklung vorherrschen sollte", denke ich, dass Ihr Gehen ungerechtfertigt ist.
Alice
3

Vielleicht hat der Interviewer absichtlich eine so dumme Frage gestellt und wollte, dass Sie 3 Punkte machen:

  1. Grundlegende Argumentation. Beide Schleifen sind unendlich, es ist schwer, über Leistung zu sprechen.
  2. Kenntnisse über Optimierungsstufen. Er wollte von Ihnen hören, wenn Sie den Compiler eine Optimierung für Sie durchführen lassen, würde dies die Bedingung optimieren, insbesondere wenn der Block nicht leer wäre.
  3. Kenntnisse über Mikroprozessorarchitektur. Die meisten Architekturen haben einen speziellen CPU-Befehl zum Vergleich mit 0 (obwohl nicht unbedingt schneller).
Rok Kralj
quelle
2

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:

unsigned long i = 0;
while (1) { if (++i == 1000000000) break; }

unsigned long i = 0;
while (2) { if (++i == 1000000000) break; }

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.

gnasher729
quelle
1
Die Argumentation "Cache-Zeilen" funktioniert nur auf einem Chip mit einem extrem kleinen Cache.
Scharfzahn
10
Dies ist nebensächlich. Fragen zur Geschwindigkeit setzen "alles andere gleich" voraus.
Jim Balter
6
@ JimBalter: Dies war keine Frage der Geschwindigkeit, es war eine Frage über einen Streit mit einem Interviewer. Und die Möglichkeit, dass ein tatsächlicher Test den Interviewer als "richtig" erweist - aus Gründen, die nichts mit seiner Argumentation zu tun haben, aber reiner Zufall sind. Das würde Sie in eine peinliche Situation bringen, wenn Sie versuchen würden zu beweisen, dass er falsch lag.
Gnasher729
1
@ gnasher729 Abgesehen von allen logischen Argumenten wäre der Fall des Zufalls, über den Sie sprechen, einen Blick wert. Aber immer noch blind zu glauben, dass ein solcher Fall existiert, ist nicht nur naiv, sondern auch dumm. Solange Sie nicht erklären, was, wie oder warum dies passieren würde, ist diese Antwort nutzlos.
user568109
4
@ gnasher729 "Dies war keine Frage der Geschwindigkeit" - Ich werde nicht über Leute diskutieren, die unehrliche rhetorische Techniken anwenden.
Jim Balter
2

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.

Nikolay Ivanchev
quelle
@djechlin - weil beide 1 CPU-Zyklus benötigen.
OnkelKing
Die Compilerkonstante faltet es zusammen, sodass es zur Laufzeit nicht einmal ausgewertet wird.
PaulHK
2

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: -

while (1 + 5 - 2 - (1 * 3) == 0.5 - 4 + ((9 * 2) / 4)) {
    if (succeed())
        break;
}

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.

ekerner
quelle
Das von Ihnen vorgenommene Rollback wird von einem Benutzer mit sehr hohen Wiederholungszahlen bearbeitet. Diese Leute kennen die Richtlinien normalerweise sehr gut und sind hier, um sie Ihnen beizubringen. Ich finde, dass die letzte Zeile Ihres Beitrags Ihrem Beitrag nichts Nützliches hinzufügt. Selbst wenn ich den Witz bekommen würde, den ich offensichtlich vermisse, würde ich ihn für zu gesprächig halten, den zusätzlichen Absatz nicht wert.
Palec
@ Palec: Danke für den Kommentar. Ich fand heraus, dass derselbe Typ viele meiner Beiträge bearbeitet hat, meistens nur, um das Abmelden zu entfernen. Also dachte ich, er sei nur ein Reputationstroll und daher sein Ruf. Haben Online-Foren die Sprache - und die allgemeinen Höflichkeiten - so stark erschöpft, dass wir unsere Schriften nicht mehr unterschreiben? Vielleicht bin ich ein bisschen altmodisch, aber es scheint einfach unhöflich, Höllen und Abschiede wegzulassen. Wir benutzen Apps, aber wir sind immer noch Menschen.
ekerner
1
Bei Stack Exchange sind Anreden, Slogans, Dankeschön usw. nicht willkommen . Dasselbe wird in der Hilfe erwähnt , insbesondere unter dem erwarteten Verhalten . Kein Teil von Stack Exchange , nicht einmal Stack Overflow , ist ein Forum - es handelt sich um Q & A-Sites. Die Bearbeitung ist einer der Unterschiede. Außerdem sollten Kommentare nur dazu dienen, Feedback zum Beitrag zu geben, nicht zur Diskussion ( Stapelüberlauf-Chat ). Und es gibt viele andere Möglichkeiten, wie sich Fragen und Antworten von einem Forum unterscheiden. Mehr dazu in der Hilfe und zum Meta Stack Overflow .
Palec
Beachten Sie, dass Sie mit mehr als 2000 Wiederholungen (Bearbeitungsberechtigung) keine Wiederholungen mehr durch Änderungen erhalten. Wenn Sie Zweifel haben, warum und Bearbeitung, mit der Sie nicht einverstanden sind, auf Ihren Beitrag angewendet wurde oder wenn Sie feststellen, dass sich jemand schlecht verhält, fragen Sie bei Meta Stack Overflow nach . Wenn der Editor das Falsche getan hat, können sie von einem Mod benachrichtigt werden (vielleicht haben sie es nicht bemerkt) oder sogar irgendwie bestraft werden (wenn das Verhalten absichtlich böswillig war). Andernfalls erhalten Sie Hinweise, warum die Bearbeitung / das Verhalten korrekt ist. Unnötige Rollbacks überladen den Revisionsverlauf und können Sie in einen Rollback-Krieg führen. Ich rolle nur zurück, wenn ich wirklich sicher bin, dass die Bearbeitung falsch ist.
Palec
Schließlich zum Unterschreiben, Begrüßen, ...: Es mag unhöflich erscheinen, diese Formalitäten nicht zu berücksichtigen, aber es erhöht das Signal-Rausch-Verhältnis und es gehen keine Informationen verloren. Sie können einen beliebigen Spitznamen auswählen, das ist Ihre Unterschrift. In den meisten Orten haben Sie auch Ihren Avatar.
Palec
1

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.

user143522
quelle
0

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.

Antonin GAVREL
quelle
Warum sollte er eine do {} while-Schleife vorschlagen? Während (1) (oder während (2)) dasselbe tut.
Catsunami
tun, während ein zusätzlicher Sprung entfernt wird, um eine bessere Leistung zu erzielen. Natürlich in dem Fall, in dem Sie wissen, dass die Schleife mindestens einmal ausgeführt werden würde
Antonin GAVREL
0

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:

#define while(x) sleep(x);

es wird in der Tat while(1)doppelt so schnell (oder halb so langsam) machen wie while(2).

chqrlie
quelle
@ MaxB: In der Tat muss der Makrotrick noch verzerrter sein. Ich denke, die neue Version sollte funktionieren, obwohl dies nicht durch den C-Standard garantiert wird.
Chqrlie
-4

Der einzige Grund, warum ich mir vorstellen kann, warum das while(2)langsamer sein würde, ist:

  1. Der Code optimiert die Schleife auf

    cmp eax, 2

  2. Wenn das Subtrahieren auftritt, subtrahieren Sie im Wesentlichen

    ein. 00000000 - 00000010 cmp eax, 2

    anstatt

    b. 00000000 - 00000001 cmp eax, 1

cmpsetzt 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.

hdost
quelle
15
cmp benötigt in beiden Fällen unabhängig davon 1 CPU-Zyklus.
OnkelKing
8
Dieser Code wäre falsch. Der richtige Code würde entweder 2 oder 1 in das Register eax laden und dann eax mit 0 vergleichen.
gnasher729