Ich benoetige ein float-Array der Dimension [64][64][64][3][3], bekomme aber "segmentation fault". Mit z.B. [64][64][32][3][3] gibt es keine Probleme. Wie kann man diese Beschraenkung umgehen? (64-Bit-Linux mit 8 GB RAM)
Maxim S. schrieb: > Ich benoetige ein float-Array der Dimension [64][64][64][3][3], bekomme > aber "segmentation fault". Mit z.B. [64][64][32][3][3] gibt es keine > Probleme. ein segmentation kommt aber nicht von einem Array. Wo tritt der fehler genau auf? Oder Versucht du das array auf dem Stack anzulegen?
Zeig mal den kompletten Code im Kontext. Im Prinzip sollte das gehen.
Peter II schrieb: > Maxim S. schrieb: >> Ich benoetige ein float-Array der Dimension [64][64][64][3][3], bekomme >> aber "segmentation fault". Mit z.B. [64][64][32][3][3] gibt es keine >> Probleme. > > ein segmentation kommt aber nicht von einem Array. Wo tritt der fehler > genau auf? Oder Versucht du das array auf dem Stack anzulegen? Ja, ich lege es auf dem Stack an. Allerdings nur, weil ich nicht wirklich weiss, wie man es auf dem Heap anlegt. Es muss auf jeden Fall ein zusammenhaengender Speicherbereich sein. Thorsten schrieb: > Zeig mal den kompletten Code im Kontext. Im Prinzip sollte das gehen. Diese Zeile fuehrt zu segmentation fault:
1 | float theArray[64][64][64][3][3]; |
> weil ich nicht wirklich weiss, wie man es auf dem Heap anlegt
new [] regelt.
Mehr Kontext. Auf dem Stack könnte das schon problematisch werden, je nach eingestelltem Stack Limit.
Maxim S. schrieb: > Ja, ich lege es auf dem Stack an. Allerdings nur, weil ich nicht > wirklich weiss, wie man es auf dem Heap anlegt. dann solltest du eventuell erstmal anfangen C zu lernen.- Auf dem Stack legt man nicht so viele Daten an.
Ich denke, ich werde aus dem [64][64][64][3][3]-Array einfach neun [64*64*64]-Arrays machen, die jeweils fuer sich zusammenhaengend im Speicher liegen muessen, was ja mit new gehen sollte.
Maxim S. schrieb: > Ich denke, ich werde aus dem [64][64][64][3][3]-Array einfach neun > [64*64*64]-Arrays machen, die jeweils fuer sich zusammenhaengend im > Speicher liegen muessen, was ja mit new gehen sollte. das andere muss auch mit new gehen.
Peter II schrieb: > Maxim S. schrieb: >> Ich denke, ich werde aus dem [64][64][64][3][3]-Array einfach neun >> [64*64*64]-Arrays machen, die jeweils fuer sich zusammenhaengend im >> Speicher liegen muessen, was ja mit new gehen sollte. > > das andere muss auch mit new gehen. So, dass ich neun zusammenahengende Speicherbereiche der Groesse 64^3 habe?
Maxim S. schrieb: > So, dass ich neun zusammenahengende Speicherbereiche der Groesse 64^3 > habe? das sollte auch gehen, aber das ganze geht auch als ein speicherbereich. Es sind doch nur 18Mbyte. Dafür braucht man auch kein 64bit system. Das ganze passt nur nicht auf den Stack. Im Heap ist das doch kein Thema.
Wenn die neun 64^3 Arrays gleichzeitig auf dem Stack liegen, fliegt dir das Ganze wieder um die Ohren.
> So, dass ich neun zusammenahengende Speicherbereiche der Groesse 64^3 > habe? Kannst auch einen großen machen. new[] regelt immernoch.
Kleiner Tipp: Cramersche Regel für Arrays. Dann braucht man nicht diese abartigen vielen Klammern.
Hier mein Lösungansatz:
1 | #include <iostream> |
2 | |
3 | using namespace std; |
4 | |
5 | class Helper { |
6 | public:
|
7 | Helper(int Nz_, int Ny_, int Nx_); |
8 | int index(int k, int j, int nz, int ny, int nx); |
9 | void print(float *data); |
10 | |
11 | private:
|
12 | int Nz, Ny, Nx; |
13 | };
|
14 | |
15 | Helper::Helper(int Nz_, int Ny_, int Nx_) { |
16 | Nz = Nz_; |
17 | Ny = Ny_; |
18 | Nx = Nx_; |
19 | }
|
20 | |
21 | int Helper::index(int k, int j, int nz, int ny, int nx) { |
22 | return nx + Nx*(ny + Ny*(nz + 2*(j + 3*k))); |
23 | }
|
24 | |
25 | void Helper::print(float *data) { |
26 | cout << "start address: " << data << endl; |
27 | cout << "first value: " << data[0] << endl; |
28 | cout << "last value: " << data[Nz*Ny*Nx - 1] << endl << endl; |
29 | }
|
30 | |
31 | int main(void) { |
32 | int Nz = 64, Ny = 64, Nx = 64; |
33 | int size = Nz*Ny*Nx*3*3; |
34 | int index; |
35 | float *a = new float[size]; |
36 | Helper h = Helper(Nz, Ny, Nx); |
37 | |
38 | for(int i = 0; i < size; i++) {a[i] = i;} |
39 | |
40 | for(int i = 0; i < 9; i++) {h.print(a + i*Nz*Ny*Nx);} |
41 | }
|
Das ist natürlich nur ein Beispiel. Im eigentlichen Quellcode soll eine Funktion (FFT-Bibliothek) die neun Nz*Ny*Nx großen Blöcke nacheinander bekommen und verarbeiten. Das habe ich in diesem Beispiel mit der Funktion Helper::print() simuliert. Ist das alles programmiertechnisch sauber?
Die maximale Stack-Größe kannst du mit "ulimit -a" nachgucken. Rechne doch mal, ob du die überschreitest -- ich schätze schon, bei dem Riesen-Array. Wie schon erwähnt wurde legt man sowas nicht auf dem Stack an.
Maxim S. schrieb: > float theArray[64][64][64][3][3]; Hmm.. wenn ich mich recht erinnere, dann kann C keine mehrdimensionalen Felder. Stattdessen sieht das so aus: theArray = [64 pointer], die jeweils auf folgendes zeigen: ---> array[64 pointern], die jeweils auf folgendes zeigen: ---> array[64 pointern], die jeweils auf folgendes zeigen: ---> array[3 pointern], die jeweils auf folgendes zeigen: ---> array[3 floats]. Du solltest besser 1 Array definieren: float theArray[64*64*64*3*3]; und deine Zugriffslogik selber organisieren. Alternativ kannst du FreePascal nehmen, denn Pascal kann nativ mehrdimensionale Felder. W.S.
W.S. schrieb: > Hmm.. wenn ich mich recht erinnere, dann kann C keine mehrdimensionalen > Felder. Stattdessen sieht das so aus: dann erinnerst du dich falsch. Das geht ohne Probleme in C. er macht dann das gleich wie du manuell machen willst.
Wenn Du nur das Stack-Problem hast, und Du auch nur eine Instanz des Arrays im lokalen Funktionsbereich benutzt, dann ist die "einfachste" Lösung: static float array[64][64][64][3][3] ; Damit bist Du wieder im (nicht initailisierten) Datensegment, anstatt auf dem Stack. Oder einfach global deklarieren. Ansonsten, die Idee mit der Indizierung über eine (Hilfs-)klasse sieht gut aus! Mach es doch konsequent und lass die Klasse auch gleich die Größe des Arrays zurückgeben. Oder ganz konsequent und die Klasse das Array verwalten. Achja, bei Deiner index Methode statt "...+2*(j+3*k)" besser "...+3*(j+3*k)"? Über const, size_t, c'tor Initialisierung etc. lass ich mal nicht aus: Das ist eher Schönheitswettberwerb... ^^ Vielleicht noch der Hinweis auf boost: http://www.boost.org/doc/libs/1_53_0/libs/multi_array/doc/user.html. Das ist in Deinem Fall aber wohl überdimensioniert. ^^ Grüße, Steffen
Peter II schrieb: > dann erinnerst du dich falsch. Das geht ohne Probleme in C. er macht > dann das gleich wie du manuell machen willst. Huch? Was für eine seltsame Argumentation deinerseits. Also hab ich mich doch richtig entsonnen: C kann keine mehrdimensionalen Felder, stattdessen werden daraus Felder von Pointern auf Felder von Pointern auf Felder von Pointern.... draus. Und nochwas : ICH will sowas überhaupt nicht manuell machen, sondern hab nur das mal explizit dargestellt, was bei C aus so einer Deklaration entsteht. Also lies bitte etwas gründlicher. W.S.
W.S. schrieb: > Huch? Was für eine seltsame Argumentation deinerseits. Also hab ich mich > doch richtig entsonnen: C kann keine mehrdimensionalen Felder, > stattdessen werden daraus Felder von Pointern auf Felder von Pointern > auf Felder von Pointern.... draus. STOP! Natürlich kann C mehrdimensionale Felder. Und auch Pointer auf Felder, wenn man's entsprechend deklariert. Kommt mir bloss nicht mit Hinterlassenschaften wie Pascal. Es soll offensichtlich immer noch rudimentäre (nicht ANSI-fähige) Compiler geben, die obigen Käse produzieren. Im Zweifelsfall vor dem voreiligen Posten: Einfach mal den Disassembler anschmeissen. Zum eigentlichen Problem: die mehrdimensionale Indizierung erzeugt u.U. sehr ineffizienten Code, und zwar meist so, wie wenn man die Indizierung von Hand rechnet (d.h. (x0, .., xn) -> Speicheradresse). Einer hat schon den "Cramer" eingeworfen... - Boeserfisch
Brater schrieb: > Kleiner Tipp: Cramersche Regel für Arrays. Dann braucht man nicht diese > abartigen vielen Klammern. Kannst du das bitte genauer erklären. Habe ich noch nie gehört und auch nichts dazu im Netz gefunden. Mir ist natürlich klar, was die Cramersche Regel ist, aber wie man sie auf Arrays anwenden kann ist mir unklar. Gruß Oliver
W.S. schrieb: > stattdessen werden daraus Felder von Pointern auf Felder von Pointern > auf Felder von Pointern.... draus. Ist mir bei normal deklarierten Arrays noch nicht untergekommen. > C kann keine mehrdimensionalen Felder Formal syntaktisch nicht, weil es sich in C anders als in Pascal um verschachtelte eindimensionale Arrays handelt. Aber trotzdem werden im Speicher keine Pointer abgelegt und in der Praxis ist der Unterschied bei letztlicher Operation mit Skalaren wirklich nur syntaktischer Natur.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.