Speicher lieber zusammen oder einzeln anlegen?
-
Eine Funktion soll eine gewisse Menge Daten anlegen und dann damit noch Dinge tun und verändert an selber Stelle speichern.
Ist es nun besser alles zuerst anzulegen und dann zu verändern. Oder in kleinen Schritten anlegen und verändern.Doofes Beispiel:
int *alle = new int[1000*1000] //anlegen for (int i; i < 1000000 ; i++) alle[i] = i; //ändern for (int i; i < 1000000 ; i++) alle[i] = alle[i]+1; ///------------------oder ----------- int **klein = new *int[1000] //anlegen for (int i; i < 1000 ; i++){ klein[i] = new int[1000]; for (int j; j < 1000 ; j++) klein[i] = i; //andere Werte als oben, spielt keine Rolle } //ändern for (int i; i < 1000 ; i++) for (int j; j < 1000 ; j++) klein[i] = klein[i]+1;
unabhängig davon ob "[]" oder "[][]" schöner ist, wurde nur im Beispiel verwendet. Geht nur darum, ob man lieber viele kleine Schritte macht oder einen großen.
-
Man nimmt lieber std::vector.
Wenn man genau weiß, wieviele Elemente man brauchen wird, nimmt man im Regelfall alles auf einen Rutsch.
Wenn man eine 2D Matrix braucht, schreibt man sich eine kleine Klasse mit operator(), die einem die Zeilen-/Spaltenrechnerei abnimmt.
-
@Fisch
Deine Frage ist zu allgemein.
Was ich sagen kann:
* Besser ein grosses Array anlegen als 1001 kleine
* Wie manni66 schon geschrieben hat besser std::vector als manuell mit new/delete rummachenUnd dann...
Also anhand deines Beispiels würde ich das folgendermassen "optimieren":int *alle = new int[1000*1000] //anlegen for (int i; i < 1000000 ; i++) alle[i] = i; //ändern for (int i; i < 1000000 ; i++) alle[i] = alle[i]+1; // => std::vector<int> alle(1000*1000); //anlegen for (int i; i < 1000000 ; i++) alle[i] = i; //ändern for (int i; i < 1000000 ; i++) alle[i] = alle[i]+1; // => std::vector<int> alle(1000*1000); for (int i; i < 1000000 ; i++) { //anlegen alle[i] = i; //ändern alle[i] = alle[i]+1; } // => std::vector<int> alle(1000*1000); for (int i; i < 1000000 ; i++) { //gleich richtig anlegen alle[i] = i + 1; }
Weil man halt unnötige Speicherzugriffe vermeiden will. Und zwar um so mehr, je grösser das "working set" ist mit dem man arbeitet.
Wenn du genaueres wissen willst, weil sich das oben gezeigte (vermutlich) nicht 1:1 auf dein konkretes Problem anwenden lässt, dann musst du konkreter fragen.
Bei sehr aufwendigen Berechnungen an Stelle des "i + 1" kann es z.B. die Geschwindigkeit der Speicherzugriffe keine Rolle spielen. Und es u.U. sogar besser sein wenn man mehrere "passes" macht. Nämlich z.B. dann wenn der "alles in einem" Code zu gross für den L1 Instruction Cache wäre, der Code für jeweils einen "pass" aber gut in den L1 Cache passt.
Und wenn Geschwindigkeit keine grosse Rolle spielt, dann schreibt man es sowieso so wie es logisch einfacher zu verstehen ist.
-
Danke für die Antworten.
Ich hatte es bei meinem Problem mittlerweile auch mit Vektoren gemacht. Der Vekor selbst wird jedoch nicht direkt benötig, sondern nur alle einzelnen Elemente für sich. Welche wiederum untereinander verknüpft sind.
Ich meine nur einmal gehört/gelesen zu haben das moderne CPU/compiler auch mehreres gleichzeitig kann. Wenn ich immer nur kleine Stücke alloziere, das dann nebenbei gleich noch gerechnet werden kann, bzw. während des rechnens schon der nächste alloziert werden kann. Bei Grafikkarten macht man das glaube ich auch.
-
Da du nur sehr vage Andeutungen machst, kann ich zu deinem konkreten Fall nichts sagen. Grundsätzlich ist es aber so, dass eine moderne CPU viele Operationen schnell parallel ausführen kann, solange sie die Daten im Cache findet und nicht auf den Hauptspeicher zugreifen muss (denn der Zugriff dauert Ewigkeiten). Wenn man also z.B. eine std::list<int> hinreichender Größe hat und diese sortiert, wird anschliessend das einfache drüber iterieren im Vergleich zu einem std::vector<int> gut messbar langsamer.
-
Fisch schrieb:
Wenn ich immer nur kleine Stücke alloziere, das dann nebenbei gleich noch gerechnet werden kann, bzw. während des rechnens schon der nächste alloziert werden kann.
So wie du das vermutlich meinst: nö, das geht so nicht.
Du kannst nicht auf einem Core gleichzeitig rechnen und Speicher allozieren. Ja, ein Core kann mehrere Dinge gleichzeitig machen, aber nicht so massiv dass new() gleichzeitig mit einer anderen ähnlich komplizierten Aktion laufen würde.
Mit mehreren Cores geht es natürlich. Nur das passiert nicht automatisch nur weil deine CPU mehrere Cores hat - das muss man entsprechend programmieren.
Tut aber denke ich alles nix zur Sache.
Wenn du 1 Mio. Elemente gleichzeitig brauchst, dann forder 1 Mio. an - mit einem Aufruf. Das ist immer schneller als 1000x je 1000 Elemente anzufordern. Weil es für die Allokator-Funktion quasi Wurst ist ob eine Anforderung über 1000 oder 1 Mio. Elemente geht. Eine Anforderung ist eine Anforderung und die braucht inetwa gleich lange. 1000 Anforderungen brauchen also 1000x so lange.
Die nächste Frage ist dann aber, ob du wirklich 1 Mio. Elemente gleichzeitig brauchst. Das können wir nicht erraten, weil du ja nicht verrätst was du eigentlich machen willst.