Heap, Stack und Performanzüberlegungen
-
Servus,
ich weiß nicht, wie ich meine Variablen anlegen soll, damit das Programm so schnell wie möglich läuft. Mir fehlen vor allem die grundlegenden Fragen für eine Entscheidungsfindung. Ebenso weiß ich nicht, wie geschickt ein Compiler arbeitet - nicht dass dieser aus meinem Laiencode hochperformante Konstrukte bildet und meine manuellen Optimierungsversuche dann darin enden, dass diese unverändert bleiben und am Ende das Programm langsamer läuft.
Aktuell weiß ich, dass es 4 Speicherformen gibt:
Codespeicher - landet im Arbeitsspeicher, die Maschinenbefehle werden der Reihe nach in Prozessorregister geschoben und abgespeichert (jetzt wo ich das aus meinem Buch lese, sagt mir das aber nichts mehr :-), vielleicht bessert einer nach ...).
Datenspeicher - hier liegen alle statischen Daten bis zum Ende des Programms (ich vermute hier liegen meine globalen Variablen).
Stackspeicher - hier liegen die Funktionsaufrufe und die zur Funktion gehörenden lokalen Variablen (ich habe mal gelesen, oft ist hier ein Limit von 1 Megabyte).
Heapspeicher - das ist der Restspeicher und dort leben die mit new angelegten Objekte. Auch er bleibt verfügbar, bis er freigegeben wird oder das Programm beendet wird.
Ich arbeite mit Netbeans und meine Programme laufen lange, sagen wir der Algorithmus braucht 2 Stunden. Nun läuft direkt ein Profiler mit und zeigt mir den Verbrauch auf dem Heap an, der ist aber ziemlich gering (meist ein paar hundert Kilobyte), ich nutze bis jetzt kein 'new', also überrascht mich das nicht. Jetzt dachte ich, wenn ich doch diesen Heap mehr beanspruche, dann kann der Rechner vielleicht schneller sein, denn mehr als die paar Kilobyte wird der Heap ja wohl anbieten können?
Ich weiß auch nicht wo meine Variablen leben, ich nutze oft Vektoren, die ja C++ selbständig bei Bedarf ausweitet - was passiert da, wo leben diese Objekte?
Hilfreich für mich wäre eine Fragekette beim Anlegen von Variablen, bei der die Antwort dann die Entscheidung für die Art der Variable ist.
Danke vorab für ein paar orientierungsgebende Ratschläge!
-
Alle dynamischen Containter - so auch vector - legen ihre Objekte standardmäßig auf dem Heap an. Prinzipiell gilt: Stackspeicher ist immer um ein Vielfaches schneller als der Heapspeicher, deshalb kann es bei Performancekritischen Programmen durchaus Sinn machen, einen Stackallokator zu verwenden. Deshalb kann man bei allen Standardcontainern einen zweiten Typ als Allokator festlegen, standardmäßig std::allocator<T>.
Edit: Für kleine Objekte könnte man statt new einen Small Object Allocator verwenden.
-
Danke erstmal,
deine Antwort war für mich nicht hilfreich, ich habe schon etwas geschaut, sowohl bei Google als auch im Breymann-Buch, fand aber zu Allocators nur Material, das mir zu hoch war, daher kann ich nicht einschätzen, ob dies überhaupt auf meinen Anwendungsfall passt.
Kannst du mir noch ein paar Schlagworte oder einen Link mit etwas verständlicherem bzw. passendem Material geben, von welchem ich weiter ins Thema eintauchen kann?
Danke vorab.
-
Du könntest deinen Anwendungsfall erläutern, dann könte man dir vielleicht besser helfen.
-
Heapspeicher ist an sich nicht langsamer, lediglich die Erzeugung und Zerstörung von Objekten mittels new und delete dauert vergleichsweise lange. Beim Zugriff gibt es keinen Unterschied.
nicht dass dieser aus meinem Laiencode hochperformante Konstrukte bildet und meine manuellen Optimierungsversuche dann darin enden, dass diese unverändert bleiben und am Ende das Programm langsamer läuft.
Das wird oft passieren. Bei performanzkritischen Codeteilen musst du immer nachmessen, welche Optimierungen in der Praxis überhaupt etwas bringen.
-
Wenn Du Spaß am Lesen hast, kann ich dir dieses Blatt empfehlen:
http://www.akkadia.org/drepper/cpumemory.pdfAußerdem noch brauchbar
http://www.agner.org/optimize/optimizing_cpp.pdfLetzteres würde ich dir aber nur empfehlen, wenn du gut C++ kannst um das dort geschriebene zu bewerten. Ich war beim LEsen nicht mit allem so ganz einverstanden. Einige Dinge die Compileroptimierungen betreffen sind aber mal ganz interessant.
Einen Algorithmus auf die Speicherverwendung zu optimieren kann eine ziemlich komplexe Sache sein. Erste Anlaufstelle für Optimierungen sind natürlich immer die Algorithmen selber, dann deren Umsetzung und dann sowas wie Cacheeffizienz.