const-Variablen aus Datei laden?
-
Hm, mir ist klar, dass der Compiler das* (EDIT: bezieht sich auf die ersten 2 Beiträge) nicht so machen kann wie ihr es beschreibt, aber ich schrieb ja (verschachtelt in einen Satz), dass es einmal spürbar schneller war, als die Variablen const waren.
Das könnte man sich auch erklären: Der Compiler könnte merken, dass da 2 Variblen const sind, also nach Konstruktion des entsprechenden Objektes. Vorher werden sie aber sowieso nicht benutzt, folglich ändern sie sich in diesem Ausdruck nie mehr.
Er könnte also auf die Idee kommen, sowas wie ein flag anzulegen, ob der Code bereits ausgeführt wurde, und wenn es das erste Mal ist, den Wert ausrechnen und "global" speichern.Mitlerweile befürchte ich jedoch, dass der Speed, den ich vorhin sah, garnicht dadurch gekommen ist, dass ich die Member const gemacht habe, und auch nicht davon weggegangen ist, dass ich diesen load-struct-hack eingebaut habe.
Ich schaffe es nämlich nicht, das zu reproduzieren...Aber theoretisch wärs doch möglich?
Es ist auch keineswegs so, dass das Microoptimierung ist:
Es soll für jeden Pixel (können also so 1 Millionen sein) komplizierte Berechnungen mit den Werten möglichst mehrmals pro Sekunde geben...P.S.:
Anscheinend ist nachdem ich überhaupt erstmal auf richtige const-globalen verzichtet habe, der enorme Geschwindigkeitsverlust nur dann aufzutreffen, wenn WIDTH != HEIGHT
kA wieso.
Das führte dann wohl vorhin zufällig zu der meiner Annahme, dass der Compiler abhängig von dem Hilfshack optimiert, denn wies aussieht ist die Optimierung abhängig von WIDTH != HEIGHT
Seeeeehr verwirrend
-
Du solltest Dich wirklich mal mit der Funktionsweise von Compilern bzw. aktueller C++-Implementierungen an sich auseinandersetzen, Du scheinst da ein paar Sachen nicht zu verstehen.
Wenn Du foo*bar sehr oft brauchst dann mach halt foobar=foo*bar; und verwende foobar statt foo*bar.

-
nman schrieb:
Du solltest Dich wirklich mal mit der Funktionsweise von Compilern bzw. aktueller C++-Implementierungen an sich auseinandersetzen, Du scheinst da ein paar Sachen nicht zu verstehen.
Wieso? Wo sind Denkfehler?
Wenn Du foo*bar sehr oft brauchst dann mach halt foobar=foo*bar; und verwende foobar statt foo*bar.

Hey, das ist garnicht so schlecht, abgesehen davon, dass es nicht so ist, dass ich foo*bar oft hintereinander brauche. Dann wär ich nämlich selbst im meiner momentanen geistig labilen Situation allein drauf gekommen. Es ist vielmehr so, dass ich das immer wieder in Funktionen ausrechne, und ich die Funktionen immer wieder aufrufen muss. Und das nun einmal auszurechnen und den Funktionen immer zu übergeben - neee, viel zu unsauber.
Aber das bringt mich auf die ja sooo geniale und unglaubiche Idee, hier zum Beispiel einfach mal ein static davor zu machen:
float foo = 1.0f / ( 2.0f * tan(Settings::instance().FOV * 3.14159265358f/180.0f * 0.5f));Aber das macht sich bei mehrzeiligen Berechnungen auch nicht so gut (wo nicht nur initialisiert wird)
Wenn dann müsste ich da wohl die oben genannte Methode mit dem flag selbst einbauen, was ich wiederrum unschön finde.
Gibts wirklich keine andere Lösung?
-
Ich würde an deiner Stelle einfach nen const-Objekt erzeugen, welches diese Variablen beinhaltet.
-
otze schrieb:
Maxi schrieb:
hier im Forum war mal ne Methode, wie man über umwege const-variablenm während der Laufzeit verändern konnte. Musste mal bissel suchen. Aber ich glaub nciht, dass dasd dann was hilft, denn optimieren tut der Compiler ja indem die Werte direkt in den Code einsetzt, und nciht bei jedem Aufruf aus ner Variablen lesen muss.
ausser,d ass es reichlich weit vom problem entfernt ist...
wenn der compiler das tun würde, dann könnte man const werte auch nicht verändern
was du meinst, sind defines.Ich finde die Antwort garnicht so abwegig. Aber er hat schon recht, helfen würde es mir nicht direkt, (glaub, nein, rate ich zumindest
).
Und warum sollte der Compiler bei "richtigen" const´s nicht einsetzen wie bei #defines?
-
spl@t schrieb:
Wieso? Wo sind Denkfehler?
Kein Compiler macht sowas von alleine und das ist auch gut so.
Wenn Du kompliziertere Funktionalität brauchst, dann muss Du in solchen Fällen selbst dafür Sorge tragen, dass zB. Speicher zugunsten der Performance verschenkt wird oä. (Was natürlich auch das Benutzen entsprechender Libraries einschließt.)
-
spl@t schrieb:
Und warum sollte der Compiler bei "richtigen" const´s nicht einsetzen wie bei #defines?
Ihr redet aneinander vorbei; bei Compiletime-Konstanten wird natürlich auch keine Text-Expansion durch den Präprozessor vorgenommen, das meinte otze.
-
@splat um Speicherplatz zu sparen, ein Compiler wird die ganzen Define-Konstanten beim optimieren auch zu einer zusammenfassen, so vermeidet er redundanz.
-
SirLant schrieb:
@splat um Speicherplatz zu sparen, ein Compiler wird die ganzen Define-Konstanten beim optimieren auch zu einer zusammenfassen, so vermeidet er redundanz.
Hu? Was meinst Du? Mit #defines hat der Compiler gar nix zu tun, das macht alles der Präprozessor.
-
SirLant schrieb:
Ich würde an deiner Stelle einfach nen const-Objekt erzeugen, welches diese Variablen beinhaltet.
Das klingt doch schonmal sehr gut!
Naja, andererseits - wie ich ja jetzt gelernt habe, wird dann trotzdem nicht so optimiert wie ichs mir wünscheAber ausprobieren muss ichs mal. Stimmt das denn dann so?
__forceinline static const Settings& instance() { static const Settings set; return set; }
-
Irgendwie verstehst Du nicht worum es geht, oder?
Du kannst noch soviele const-Objekte erstellen; solange die Dinger nicht compiletime-konstant sind, wird da einfach nichts so früh direkt berechnet.Und was Deine letzte Idee bringen soll weiß der Kuckuck.

-
nman schrieb:
SirLant schrieb:
@splat um Speicherplatz zu sparen, ein Compiler wird die ganzen Define-Konstanten beim optimieren auch zu einer zusammenfassen, so vermeidet er redundanz.
Hu? Was meinst Du? Mit #defines hat der Compiler gar nix zu tun, das macht alles der Präprozessor.
Wenn du ein #define foo 2 hast steht doch überall im Programm beim
kompilieren die 2 statt dem foo und diese ganzen const-Objekte kann der Compiler
ja gegen ein const-objekt austauschen.
-
SirLant schrieb:
Wenn du ein #define foo 2 hast steht doch überall im Programm beim kompilieren die 2 statt dem foo und diese ganzen const-Objekte kann der Compiler ja gegen ein const-objekt austauschen.
Entweder ich habe Dich gerade arg missverstanden, oder das ist großer Blödsinn.

edit: Nix für ungut, ich bin hundemüde, vielleicht hab ich einfach nicht verstanden was Du meinst, aber wenn ich sowas kompiliere
#include <iostream> #define foo 2 int main() { std::cout << foo * bar; std::cout << foo * 5; // und so weiter }dann wird der Präprozessor alle Vorkommnisse von foo stur durch 2 ersetzen und der Compiler garantiert danach kein gemeinsames Objekt für die einzelnen Integerliterale anlegen.
-
nman schrieb:
Irgendwie verstehst Du nicht worum es geht, oder?
Du kannst noch soviele const-Objekte erstellen; solange die Dinger nicht compiletime-konstant sind, wird da einfach nichts so früh direkt berechnet.Und was Deine letzte Idee bringen soll weiß der Kuckuck.

Doch doch, ich schrieb doch deutlich, dass ich weiß, dass es nichts bringen kann, von der Performance.
Die "Idee" war einfach die Umsetzung von SirLants Vorschlag. Ich wollte das Objekt const machen, und fragen, wie genau das geht, da es ja ein Singleton ist.
Und sei es nurnoch wegen const correctness.Das Thema hat sich jetzt sowieso erledigt, denn ich habe meinen Speed, sobald ich _entweder_ Breite und Höhe auf den selben Wert setze (sehr merkwürdig, sagte ich auch bereits) _oder_ der Funktion als Parameter Breite und Höhe per Settings::instance().WIDTH bzw .HEIGHT übergebe, anstatt in der Funktion selbst darauf per Settings::instance().WIDTH bzw .HEIGHT zuzugreifen
Dabei meine ich Geschwindigkeitsunterschiede von ca. 100-fach für das gesamte Programm.
Erstaunlich, nicht? Bei Interesse kann ich die Funktion auch posten.
-
spl@t schrieb:
Erstaunlich, nicht? Bei Interesse kann ich die Funktion auch posten.
Ja, bitte, würd ich mir gerne am Vormittag anschaun wenn ich Zeit habe; mittlerweile bin ich nicht mehr allzu aufnahmefähig...

-
vector3 getPixelColor(const vector3& cam_pos, const vector3& cam_dir, const vector3& up_vector, const vector2& pixel, vector2& screensize) { const float INV_FAC = 1.0f / ( 2.0f * tan(Settings::instance().FOV * 3.14159265358/180.0f * 0.5f)); vector3 screenpoint(cam_pos); screenpoint = screenpoint + cam_dir; vector3 horizontal_offset = CrossProduct(cam_dir, up_vector); vector3 vertical_offset = -up_vector; screenpoint = screenpoint + horizontal_offset * (pixel.x - screensize.x * 0.5f) / (screensize.x * INV_FAC); screenpoint = screenpoint + vertical_offset * (pixel.y - screensize.y * 0.5f) / (screensize.y * INV_FAC * (screensize.y/screensize.x)); Ray ray(cam_pos, screenpoint, 0); if (Settings::instance().ANTIALIASING) { float x_offset = 0.5f / (screensize.x * INV_FAC); float y_offset = 0.5f / (screensize.y * INV_FAC * (screensize.y/screensize.x)); horizontal_offset = horizontal_offset * x_offset; vertical_offset = vertical_offset * y_offset; Ray ray1(cam_pos, screenpoint + horizontal_offset, 0); Ray ray2(cam_pos, screenpoint - horizontal_offset, 0); Ray ray3(cam_pos, screenpoint + vertical_offset, 0); Ray ray4(cam_pos, screenpoint - vertical_offset, 0); Ray ray5(cam_pos, screenpoint + horizontal_offset + vertical_offset, 0); Ray ray6(cam_pos, screenpoint - horizontal_offset + vertical_offset, 0); Ray ray7(cam_pos, screenpoint + horizontal_offset - vertical_offset, 0); Ray ray8(cam_pos, screenpoint - horizontal_offset - vertical_offset, 0); return trace(ray, Settings::instance().DEPTH, Settings::instance().RADIOSITY) * 0.25f + (trace(ray1, Settings::instance().DEPTH, Settings::instance().RADIOSITY) + trace(ray2, Settings::instance().DEPTH, Settings::instance().RADIOSITY) + trace(ray3, Settings::instance().DEPTH, Settings::instance().RADIOSITY) + trace(ray4, Settings::instance().DEPTH, Settings::instance().RADIOSITY)) * 0.125 + (trace(ray5, Settings::instance().DEPTH, Settings::instance().RADIOSITY) + trace(ray6, Settings::instance().DEPTH, Settings::instance().RADIOSITY) + trace(ray7, Settings::instance().DEPTH, Settings::instance().RADIOSITY) + trace(ray8, Settings::instance().DEPTH, Settings::instance().RADIOSITY)) * 0.0625; } return trace(ray, Settings::instance().DEPTH, Settings::instance().RADIOSITY); }und Aufruf per:
vector3 color = getPixelColor(cam.pos_, cam.direct_, vector3(0.0f, 1.0f, 0.0f), vector2(x, y), vector2(Settings::instance().WIDTH, Settings::instance().HEIGHT));ist ca. 100 mal schneller als wenn statt screensize.x Settings::instance().WIDTH und statt screensize.y Settings::instance().HEIGHT geschrieben wird und die Funktion 1nen Parameter weniger hat.
Bin übrigens auch nicht mehr so richtig bei der Sache
Oh, immerhin, ich seh grad, eine Division kann ich mir schenken indem ich INV_FAC zu FAC mache. Aber das ist jetzt irrelevant
-
Jesus Christus! Da blickt ja kein Mensch mehr durch.
-
nman schrieb:
dann wird der Präprozessor alle Vorkommnisse von foo stur durch 2 ersetzen und der Compiler garantiert danach kein gemeinsames Objekt für die einzelnen Integerliterale anlegen.
Wenn der Compiler garantiert diese _nicht_ zu einem zusammenzufassen, dann ist das was ich gesagt habe blödsinn.
-
SirLant schrieb:
Wenn der Compiler garantiert diese _nicht_ zu einem zusammenzufassen, dann ist das was ich gesagt habe blödsinn.
Kennst Du einen Compiler der für Integer-Literale mit gleichem Wert ein gemeinsames konstantes Objekt anlegt?
Ich ehrlich gesagt nicht und ich glaub auch wirklich nicht dass das klug wäre; uU mal warten was die Profis dazu sagen.
-
otze schrieb:
Jesus Christus! Da blickt ja kein Mensch mehr durch.

Aber wenn du dir den großen Block in der Mitte mit den langen Zeilen wegdenkst, ist es nun wirklich nich mehr viel. Und den kannst du dir ruhig wegdenken, weil dieser komische Performanceunterschied auch dann auftritt, wenn ich ANTIALIASING = false setze.
Dann ist es ja bloß noch ein bisschen Mathematik, aber auch nicht so schwer (das hat sich ein 10.-Klässler ausgedacht, der die letzte Mathearbeit verhauen hat...)
