const-Variablen aus Datei laden?
-
Hallo,
irgendwie stehe ich vor einem Problem: Ich möchte ein paar die gesamte Programmlaufzeit unveränderliche Werte aus einer Datei laden, das heißt natürlich, dass sie sich doch verändern, aber halt nur am Anfang.
(Optionen wie Auflösung etc.)
Nun sollten diese Werte aber schon const sein, damit mein Compiler schön optimieren kann und sowas wie WIDTH / HEIGHT zur Compilezeit ausrechnen kann.
Habs jetzt so gemacht, dass ich ein Singeton mit den Options-Variablen als Konstanten habe, die im Constructor aus den Werten eines weiteren statischen Members des Singletons, nämlich einer Struct, die noch einmal alle diese Optionen als nicht konstante (also "ladbare") Member besitzt, initialisiert werden.
Und diese Struct besitzt einen Constructor, der die Daten in die Struct lädt.
Ich hoffe das war noch verständlich.Das Problem:
- Ich find diesen Hack extrem hässlich.
2 und viel wichtiger) Es funzt zwar, aber der Compiler optimiert doch nicht! (VC 7, Release). Anscheinend ist ihm das zu viel, denn wenn ich das mit dem "aus-Datei-laden" und dieser Hilfsstruct, die dieses tut, weglasse, und die Werte im Singleton direkt im Konstruktor initialisiere (z.B. : WIDTH(320)), läuft alles viel schneller!
Bin ich irgendwie blind, oder ist das wirklich schwierig/ unmöglich zu lösen?
Das zur Kompilezeit die Daten nicht bereitstehen können, ist mir ja klar, aber die Optimierung in letztgenanntem Fall zeigt doch, dass der Compiler im Prinzip schlau genug ist, Code einzubauen, der den Wert, sofern arimethische Ausdrücke nur aus Konstanten (die wie gesagt zur Compilezeit nicht bereitstehen) bestehen, nur einmal ausrechnet und ihn dann speichert. Zumindest wenn man keinen komischen Hack dazu bastelt...Danke
- Ich find diesen Hack extrem hässlich.
-
wie soll der compiler etwas optimieren, wenn er es zur compilezeit noch nicht einmal kennt? immerhin ist es in einer Datei und nicht im quellcode. Der compiler kann aber, wie dus ja schon gesagt hast, sofort optimieren, wenn er sieht, dass zur compiletime im ctor schon die werte bekannt sind.
1+2 kann der compiler ausrechnen, x+y nicht.
-
spl@t schrieb:
...damit mein Compiler schön optimieren kann und sowas wie WIDTH / HEIGHT zur Compilezeit ausrechnen kann.
Denk darüber noch mal nach; wie soll das denn auch funktionieren können?

Du lädst zur Laufzeit zwei Variablen und die soll der Compiler zur Compilezeit kennen?
Du betreibst IMO Mikrooptimierung; natürlich kannst Du diese Members const machen; zur Compilezeit ausgerechnet wird da aber trotzdem nix, was auch nicht wichtig/ nötig sein sollte.
-
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.
-
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.
-
Nein, ich glaube er meint mutable oä, aber das hilft alles nichts; dass das alles nix am Problem ändert wisst ihr ja...
-
otze schrieb:
1+2 kann der compiler ausrechnen, x+y nicht.
Doch, wenn x und y zur Compiletime bekannt sind, schon, andernfalls kann das natürlich beim Kompilieren noch nicht ausgerechnet werden.
(Ich weiß dass Du das weißt, aber der OP ist sich darüber uU nicht im Klaren.)
-
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.