Wieso schreiben C++ Progger for(int i=0; i!=99... anstatt i<99
-
Bashar schrieb:
Theorien-Erfinder schrieb:
Vielleicht wird != um eine Tausendstel Sekunde schneller ausgewertet als <. Wäre gar nicht so unlogisch. Bei != kann die Funktion beim erstbesten Bit zurückkehren, das nicht übereinstimmt. Bei < ist die Sache nicht so eindeutig, bzw. müssen im Durchschnitt immer ein paar Bits mehr miteinander verglichen werden -> ergo -> dauert deshalb eventuell minimal länger. Ist aber nur eine Theorie.
Nette Theorie, sie ignoriert leider die Funktionsweise von Rechnern

Newsflash: Auch von Compilern. gcc scheint zumindest solche Standardmuster zu erkennen und generiert gleich nur eine jne-Instruktion (jump if not equal).
Auch Bashar glaubt, dass sich Maschinenbefehle nicht in der Laufzeit unterscheiden.
Und ich hab' keine Ahnung von der Funktionsweise eines Rechners. Ein Compiler, der optimiert, ohne dass man es ihm anschafft, ist der größte Feind eines Programmierers.
mfg
-
ihr seid ja alle lol, ich meinte "warum schreiben manche for(;;) statt while(true)" nicht wirklich als frage, denn wie ich weiter geschrieben hab "ist doch scheiss egal...

-
TheorienErfinder schrieb:
Auch Bashar glaubt, dass sich Maschinenbefehle nicht in der Laufzeit unterscheiden.

Wo liest du das raus?
-
Oh man, geringfügig schneller oder langsamer...
Wenn ihr das wissen wollt, guckt Euch den Assembler der betreffenden Stelle an, und sucht Euch die Cycles raus, die die Befehle haben. Alles andere ist Hokuspokus.
-
kreater schrieb:
warum schreiben manche for(;;) statt while(true)?
is doch scheiss egal...
Nicht wirklich, denn "while(true)" liefert überflüssige Compilerwarnungen, die man nicht wirklich braucht. "while(true)" ist somit die objektiv schlechtere Variante.
-
TheorienErfinder schrieb:
Man ersetze
i & 1
jeweils durch
i % 2Oberflächlich betrachtet geschieht das gleiche: Man möchte herausfinden, ob eine Zahl ungerade ist. Es wird auch jeweils nur ein einziger Maschinenbefehl verwendet (BITAND bzw. MODULO). Trotzdem ist die Laufzeit der i % 2 - Variante erheblich länger.
Es gibt noch hunderte solcher Fälle.mfg
das erkennt sogar der Mensch, dass das eine ne Division ist und das andere ein wesentlich schnelleres And.
MS VC++ 2008 EE z.B. optimiert das bereits in der Debug-Version (da es sich um einen konstanten Parameter handelt).
Das ist genauso wie (i * 4) und (i << 2).laut intel ist je/jne (!=) genauso schnell wie jg/jl (<) oder ja/jb (<),
tiefer kann man nicht gehn.--> + iteratoren.
--> + blaaaaa.
-
Theorien-Erfinder schrieb:
So, und ab sofort ist es keine Theorie mehr, sondern eine Tatsache:
!= ist geringfügig schneller als <Nope. Von der Theorie her hast du schon recht, ein Vergleich auf Gleichheit bzw Ungleichheit lässt sich effizienter implementieren. Die Praxis sieht nur ein klein wenig anders aus. x86 Legacy Code kennt nur eine allgemeine Vergleichsinstruktion, cmp. Dabei wird alles mögliche in Betracht gezogen, kleiner, gleich oder grösser, und die entsprechenden Flags gesetzt. Mittels Sprungbefehlen (jxx) können diese dann weiterverarbeitet werden.
So, und hier noch meine Ergebnisse (GCC4.3):
Dauer !=: 615678 QueryTakte Es gibt 100000000 ungerade Zahlen Dauer <: 927758 QueryTakte Es gibt 100000000 ungerade ZahlenWie du sehen kannst, unterscheiden sich die Laufzeiten enorm. Interessant wird es aber erst, wenn man sich mal das Assembler Listing der Schleifen anschaut anschaut:
L2: mov eax, edx and eax, 1 add ebx, eax inc edx cmp edx, 200000000 jne L2 [...] L3: mov eax, edx and eax, 1 add ebx, eax inc edx cmp edx, 200000000 jne L3Wie du sehen kannst, der Maschinencode ist identisch. Was also verursacht die unterschiedliche Laufzeiten? Es sind nicht die Operationen != oder <. Die Ursachen sind bei Arbeitsweise der CPU selbst zu suchen, wie Code Alignment, Prefetching, Caching, usw.
-
mal erlich leute,
wie wichtig ist das für die "meisten"(betont) Programme wirklich
Na gut ein Augenzwinkern mehr zeit gehabt.
Es gibt weiß Gott andere Dinge zu verbessern
Fencer over and out

-
Das ist nicht das Thema. Natürlich gibt es wichtigere Dinge. Aber genau für solche Sachen sollte man sich mal 5 Minuten Zeit nehmen. Später werden daraus sowieso Automatismen und tragen zum Unterschied zwischen guten Programmierern und "Hobby Proggern" bei.
-
Fencer schrieb:
mal erlich leute,
wie wichtig ist das für die "meisten"(betont) Programme wirklich
Na gut ein Augenzwinkern mehr zeit gehabt.
Es gibt weiß Gott andere Dinge zu verbessernDiese Sichtweise könnte man in nahezu jedem Thread vertreten. Es gibt immer etwas Wichtigeres, trotzdem sollte man auch Dinge wie dieses beachten. Aber du brauchst ja nicht mitzudiskutieren, wenn es deiner Meinung nach unwichtig erscheint.
Abgesehen davon hat < den Vorteil, dass bei Manipulationen der Zählvariable innerhalb der Schleife trotzdem eine korrekte Abbruchbedingung bleibt (wie bereits gesagt wurde).
-
Nexus schrieb:
Abgesehen davon hat < den Vorteil, dass bei Manipulationen der Zählvariable innerhalb der Schleife trotzdem eine korrekte Abbruchbedingung bleibt (wie bereits gesagt wurde).
...und vor allem auch korrekt funktioniert, falls die Bedingung schon am Anfang nicht erfüllt ist.
-
Nexus schrieb:
Diese Sichtweise könnte man in nahezu jedem Thread vertreten. Es gibt immer etwas Wichtigeres, trotzdem sollte man auch Dinge wie dieses beachten. Aber du brauchst ja nicht mitzudiskutieren, wenn es deiner Meinung nach unwichtig erscheint.
Wenn es immer etwas wichtigeres gibt, hat es keinen Sinn dies hier zu beachten, weil es n Dinge gibt, die eine höhere priorität haben. Dazu gehören Code Lesbarkeit, Code Konventionen usw. Du musst auch anderen deswegen nicht den Mund verbieten(oder es anderen nahe legen nicht mitzudiskutieren) weil es ein absolut berechtigter Einwand ist.
In C++ vertraust du dem Compiler in allen microoptimierungen. Das hat durchaus Sinn, denn oftmals kennst du den Kontext des Codes/der funktion/der Klasse nicht, und C++ Codeoptimierungen sind sehr oft kontextabhängig(templates und konsorten). Also sagen wirs kurz und knapp: Oft weis der Compiler einfach mehr als du. Was er draus macht ist eine andere Geschichte, aber wenn der Compiler deinen Optimierten Code nachträglich wieder ganz anders umsetzt, war alles Umsonst

Hinzu kommt, dass diese mikrooptimierungen Entwicklungszeit kosten, und der Effekt ist oftmals nichtmal messbar. Ein Programm verbringt durchschnittlich 95% seiner Ausführungszeit in 10% des Codes. Wenn also etwas optimiert werden muss, dann diese 10%, welche Teile das genau sind, weist du allerdings erst nach einem profiler durchlauf. Und wer sagt, dass so ein durchlauf überhaupt stattfindet? Wenn das Programm schnell genug ist, und alle Anforderungen erfüllt, dann will ich code wartbarkeit nicht gegen geschwindigkeit tauschen.
Mein Prof in Datenstrukturen sagt eigentlich jede Vorlesung: "sie können optimieren wie sie wollen, aber haben sie auch nur einen unnötigen Festplattenzugriff, war alles umsonst".
Abgesehen davon hat < den Vorteil, dass bei Manipulationen der Zählvariable innerhalb der Schleife trotzdem eine korrekte Abbruchbedingung bleibt (wie bereits gesagt wurde).
Das ist korrekt. Aber warum sollte ich in dieser Situation überhaupt eine normale zählschleife wählen? Wenn ich eh schon in der indexreinhenfolge rumspiele ist es nur eine zusätzliche Fehlerquelle, wenn die Schleife am Ende nochmals von selbst Inkrementiert.
Das tolle daran gleich was anderes zu nehmen ist auch, dass jeder weis, dass in der Schleife irgendwas *komplizierteres* als ne simple inkrementierung stattfindet, ein for-Schleifenkopf erweckt nunmal den Eindruck, dass man nur stupide irgendwas wiederholen will. Noch ein schicker kommentar vor das while konstrukt, und dein Code ist gleich viel schöner und lesbarer.
...und vor allem auch korrekt funktioniert, falls die Bedingung schon am Anfang nicht erfüllt ist.
Das wäre dann aber ein wirklich netter Seiteneffekt, der seine eigenen Kommentarzeilen braucht. Und wenn ich eh schon kommentare setzen muss, spricht nichts dagegen dann statt != ein < zu verwenden.
-
Es gibt Systeme, auf denen < vs. != tatsächlich zu einem messbaren und signifikanten Unterschied führt. Ein Szenario ist z.B. ein 8-Bit-Mikrocontroller und eine Zählschleife mit einem 16-Bit-Counter. Weil man hier mehr als eine Maschinenanweisung für den Vergleich braucht, kann ein Test auf "ungleich" kürzeren Code erzeugen als einer auf "kleiner als". Vorausgesetzt natürlich der Compiler erkennt diese Optimierung nicht selbst und vorausgesetzt die Maschinenbefehle des Mikrocontrollers erfordern diese Differenz.
-
otze schrieb:
Wenn es immer etwas wichtigeres gibt, hat es keinen Sinn dies hier zu beachten, weil es n Dinge gibt, die eine höhere priorität haben. Dazu gehören Code Lesbarkeit, Code Konventionen usw.
Es gibt immer n Dinge, die eine höhere Priorität haben. Ich glaube kaum, dass jemand so perfekt programmiert, dass er nur noch solche Luxusprobleme beachten muss. Und selbst wenn der Compiler einem die Möglichkeit nimmt, selbser eine Änderung zu bewirken, heisst das noch lange nicht, dass es nicht angebracht ist, die Sache zumindest in der Theorie genauer anzuschauen.
Ich bleibe bei meiner Meinung: Diese Ansicht kann man nahezu überall bringen; die Tatsache, dass es wichtigere Dinge gibt, ist kein Argument.otze schrieb:
Du musst auch anderen deswegen nicht den Mund verbieten(oder es anderen nahe legen nicht mitzudiskutieren) weil es ein absolut berechtigter Einwand ist.
Ich wollte ihm nicht sagen, er dürfe hier nicht mitdiskutieren. Aber es ist doch so, dass wenn ihn diese Kleinigkeit nicht interessiert, ist es ja ihm überlassen, ob er mitredet oder nicht. Was deine Unterstellung betrifft: Ich finde es übrigens genau so daneben, sich gegen eine Diskussion über ein Thema zu stellen mit dem Grund, es gäbe Wichtigeres.
otze schrieb:
Das ist korrekt. Aber warum sollte ich in dieser Situation überhaupt eine normale zählschleife wählen? Wenn ich eh schon in der indexreinhenfolge rumspiele ist es nur eine zusätzliche Fehlerquelle, wenn die Schleife am Ende nochmals von selbst Inkrementiert.
Klar ist es besser, man verwaltet in einem solchen Fall das ganze Indexmanagement selber. Trotzdem wird es in der Praxis nicht selten vorkommen, dass bei einer normalen For-Schleife (mit automatischer Inkrementierung) im Schleifenrumpf am Index rumgespielt wird.
Aber wenn man wegen des Compilers sowieso keinen Einfluss auf diese Mikrooptimierung hat, ist es wohl auch legitim, < zu verwenden, oder?
-
Selbstverständlich haben diese überlegungen ihre berechtigungen aber eben erst wenn (wie otze sagt) alles andere erledigt ist.
"Wer zuviel auf kleine Dinge achtet verliert den Blick für das wirklich Große"
hab ich leider vergessen wer das gesagt hatDas ist jetzt alles was ich zu dem Thema zu sagen hab

Gute Nacht an alle
Fencer
-
Fencer schrieb:
Selbstverständlich haben diese überlegungen ihre berechtigungen aber eben erst wenn (wie otze sagt) alles andere erledigt ist.
Wird dieser Fall überhaupt jemals eintreten?
Ich behaupte ja nicht, man solle nicht auch die wichtigen Probleme beachten. Nur denke ich, es ist auch nachvollziehbar, dass es Leute gibt, die eben auch kleinere Probleme interessieren.
Fencer schrieb:
"Wer zuviel auf kleine Dinge achtet verliert den Blick für das wirklich Große"
Dem stimme ich auch zu, man muss sich eben im Mass um solche Luxusprobleme kümmern. Aber ich befürchte deswegen nicht, dass es viele Programmierer gibt, die sich wegen solcher Angelegenheiten nicht mehr um den "wichtigeren" Code kümmern können.

-
Nexus schrieb:
Aber wenn man wegen des Compilers sowieso keinen Einfluss auf diese Mikrooptimierung hat, ist es wohl auch legitim, < zu verwenden, oder?
Wurde ja nicht gesagt, dass mans nicht verwenden dürfte, nur steht das berechtigte Argument im raum, dass man sich der Iteratorsyntax anpassen sollte. Bisher konntest du auch noch kein Argument nennen, warum in einer simplen otto-normal-zählschleife ein < besser als ein != sein sollte, und solange du da kein gegenargument hast, solltest du dir überlegen, ob es nicht besser ist einfach nur der Codestruktur wegen, hier eine einheitlichkeit zwischen iteratoren, zählschleifen und zeigern reinzubringen. Der kleinste gemeinsame nenner ist dort !=.
-
Hier sind wieder ne ganze Menge Phollbrophyoptimierer am Werk.
-
Ich will eigentlich nicht darauf beharren, selber nur < zu verwenden, deshalb ergreife ich hier auch nicht wirklich Partei für einen der beiden Operatoren. Ich frage eben nach, weil ich selber nicht sicher bin

Aber ich konnte mich von beiden nicht richtig überzeugen lassen; es scheinen eigentlich nur ästhetische Gründe (Konsistenz) für != zu sprechen...