Ein paar Performance-Fragen
-
Maxi schrieb:
Bigt es einen Zeitunterschied beim zugreifen auf globale oder lokale oder static-Variablen?
Ich schätze mal nicht. IMO gibt es nur einen zeitlichen Unterschied beim Anlegen und Zerstören der Variablen zwischen global und lokal. Statische Variablen sind glaub ich auch global, nur dass der Gültigkeitsbereich eingeschränkt ist. Korrigiert mich...
@Mastah: Für mich hat sich das Ganze schon ein bisschen so angehört, wir haben dann auch ewig über premature Optimization gesprochen, usw., obwohl ich mir jetzt auch nicht 100%ig sicher war.
Ich nutze übrigens keine Kristallkugel, sondern einen der sehenden Steine aus Herr der Ringe.
-
Maxi schrieb:
Bigt es einen Zeitunterschied beim zugreifen auf globale oder lokale oder static-Variablen?
...
-
Du magst lachen ich hab schon viele gesehen die so coden Einer davon ist mein Nachbar, der ruft jede funktion mit Assembler auf und sagt das das schneller seine als normal. Ob das stimmt oder net ist mir relativ schnuppe War ja nurn beispiel
Stimmt nicht. Es gibt nur "eine" Möglichkeit eine Funktion aufzurufen und somit kann zwischen dem was der Kompiler hinsetzt und ASM kein Unterschied sein!
- Dauert es länger, mit new ein Array zu definieren als direkt mit konstantem Index
Nur beim allokiren und freigeben gibt es einen Unterschied. Bei new muss erst eine Stelle im Heap gefunden werden die gross genug ist. Allerdings kann es sein, dass new char[16] schneller ist als char[64]! Und da man bei Stack allocation oftmals Puffer braucht den man bei new nicht braucht...
- Was ist schneller?
memcpy da du deine Schleife nicht optimirt hast!
int*i1 = ar_1; int*i2 = ar_2; for(int i = 0; i < 6; i++) *(i1++)=*(i2++);
Die Schleife oben ist schneller als memcpy da der Funktionsaufruf weg fällt. Allerdings haben manche Kompiler auch einen Schalter Funktionen wie memcpy zu inlinen womit es gleichstand wäre.
Bigt es einen Zeitunterschied beim zugreifen auf globale oder lokale oder static-Variablen?
statische Variablen sind globale Variablen die nur in einem scope sichtbar sind (wie schon von Optimizer erklärt).
-
hallo schrieb:
Die Schleife oben ist schneller als memcpy da der Funktionsaufruf weg fällt. Allerdings haben manche Kompiler auch einen Schalter Funktionen wie memcpy zu inlinen womit es gleichstand wäre.
Nein.
ich glaube kaum ein compiler setzt für memcpy einen funktionsaufruf.aber er kann, falls es besser ins alignment des codes passt...
-
Hi,
@Maxi: Warum fragst du eigentlich diese ganzen (trivialen) Sachen hier?
Erstens känntest du das alles selbst mit einem Profiler (oder meinetwegen auch ohne: Jede Variante 100000 laufen lassen und Zeit mit time() merken) oder zweitens einfach mal überlegen: Wäre eine globale Variable schneller als eine statische, warum sollte der Compiler dann nicht einfach jede statische Variable intern als globale verwenden?
ChrisM
-
Jetzt bringst du mcih in Verlegenheit...
Ich war vorhin dabei mir zu überlegen, wo ich meine Engine denn schneller machen könnte und da kamen mir eben diese Ideen/Fragen. Und ich bin eher so einer, der die frage dann im Forum stellt und die nciht erst versucht sie selbst zu beantworten :). Áber jetzt weiß ich wenigstens, dass ich nith an den kleinen Stellen optimieren sollte, sondern noch mal direkt in die algorithmen schauen und gucken was da zu machen wäre
-
@c++eus
da stellt sich nur die Frage, ob das etwas ausmacht.
das habe ich auch nicht behauptet. Nur kann man allgemein sagen, dass Heap-Allokierung langsammer oder genauso schnell wie Stack-Allokierung ist, fertig aus.
ALso, die Funktion ist halb implementiert gewesen, jetzt ist sie es ganz und funktioniert einwandfrei. So, um noch etwas Stoff einzubringen noch ne Frage:
Bigt es einen Zeitunterschied beim zugreifen auf globale oder lokale oder static-Variablen?
lol, entweder hast du den Thread nicht gelesen oder wolltest einfach die ständigen Warnungen vor Premature-Optimisation ignorieren
-
Hi,
gut, da du an einer Engine arbeitest, kann ich dir ja mal ein paar Tipps geben, wo du wirklich Performance raushauen kannst und nicht nur ein paar läppsche Prozessorticks:
- Daten größer 4 Byte immer (ok, gibt Ausnahmen, aber fast immer) per Reference und nicht per Value übergeben, vor allem niemals Strings als Value (also std::string statt const std::string&) übergeben!
- Wenn du mit DirectX arbeitest, kannst du vor allem mit richtigen Lock Flags bei Vertex und Index Buffern, sowie Texturen & co und einem guten Rendersystem (evtl. Multithreading), das immer CPU und GPU nutzt und nicht erst z.B. die KI macht und währenddessen die GPU idlen lässt und dann alles rendert, einiges rausschlagen!
- Exceptions und Polymorphismus (+ RTTI) sind zwar inzwischen nicht mehr so tragisch, auch nicht in einer Engine, aber nicht an zeitkritischen Stellen. Vor allem, weil Exceptions auch Overhead bringen, wenn sie nicht geworfen werden!
Also nicht unbedingt in den kleinen, hochoptimierten Mathefunktionen Exceptions verwenden
- Keine richtige Optimierung, aber: Soviel wie möglich vorher berechnen und nicht jeden Frame! (evtl. Lookuptable für Sinus & co erstellen, musst halt abwägen, ob eine Lookuptable sich heutzutage noch lohnt)
- Große nicht-temporäre (kann man da persistente sagen?) Objekte eher auf dem Heap erstellen und nicht den Stack damit zumüllen
- new/delete so selten wie möglich verwenden, am besten mit einem eigenen Memory Manager die zwei (+ new[]/delete[]) überladen und dann immer schön große Heaphappen allokieren.Das sollte dir mehr bringen als hier und da einen luschen Tick.
ChrisM
-
ChrisM schrieb:
- Exceptions und Polymorphismus (+ RTTI) sind zwar inzwischen nicht mehr so tragisch, auch nicht in einer Engine, aber nicht an zeitkritischen Stellen. Vor allem, weil Exceptions auch Overhead bringen, wenn sie nicht geworfen werden!
Allerdings sind viele if() auch lahm, wenn man immer so die Fehler abfangen muss...
Ne, das wichtigste ist: klarer code und optimieren wo der Profiler es sagt. Alles andere ist blödsinn.
-
Hi,
ja, die if()s sollte man natürlich auch weglassen.
Klar sollte man normalerweise immer erst die übergebenen Werte des Benutzers validieren, aber in einer Funktion, die schnell sein muss, muss ich mich halt darauf verlassen, dass der Benutzer nicht so dumm ist und z.B. gerade 0 als Divisor wählt.
ChrisM
-
- Wie schnell eine Anweisung ausgeführt wird, hängt von vielen Faktoren ab (und zum großen Teil, was zuvor gemacht wurde)
- Wenn du deinen Code schneller machen willst, solltest du nicht fragen: "Ist das schneller?", sondern "lohnt sich das?" Fast immer erkauft man sich schnelleren Code mit höherer Komplexität - und "rein nach Gefühl" irrt man sich ziemlich oft.
Checkliste - von oben nach unten abarbeiten:
- Erst gucken (Profiler, Zeit stoppen, o.ä.)
- bestmöglicher Algorithmus
- Organisation der Datenstrukturen
- "low-Level"-Optimierungen wie die von dir angesprochenen
Wenn du "nur aus Neugier" fragst, solltest du dich vielleicht mal eine Weile mit Assembler beschäftigen...
-
ChrisM schrieb:
Klar sollte man normalerweise immer erst die übergebenen Werte des Benutzers validieren
da mache ich recht oft ein assert()
das ist so schön schnell
-
ChrisM schrieb:
Hi,
ja, die if()s sollte man natürlich auch weglassen.
Klar sollte man normalerweise immer erst die übergebenen Werte des Benutzers validieren, aber in einer Funktion, die schnell sein muss, muss ich mich halt darauf verlassen, dass der Benutzer nicht so dumm ist und z.B. gerade 0 als Divisor wählt.
ChrisM
Sehe ich genauso. Mir ist allerdings nicht klar, warum Exceptions, die nicht geworfen werden, Overhead bringen. Die ifs bremsen natürlich. Bei zeitkritischen Funktionen, die Argumente übernehmen, verwende ich dann assert (fällt ja im Release weg), so dass ich mir nach ausreichender Testphase einigermaßen sicher sein kann, dass die Funktion richtig bedient wird.
@peterchen: Man könnte vielleicht noch erwähnen, dass der vierte Punkt fast nie notwendig ist, amsonsten full ack.
@Maxi: Assembler ist vielleicht deshalb interressant, weil man dadurch einen guten Einblick bekommt, was der Prozessor eigentlich wirklich tut und was er bei "if (bla)" zu fressen kriegt. Aber besser als der Compiler optimieren kann von uns wahrscheinlich fast keiner.