[C++] multi-dimensional arrays

Pagina: 1
Acties:
  • 194 views sinds 30-01-2008
  • Reageer

  • PrinsEdje80
  • Registratie: Oktober 2001
  • Laatst online: 01-01 15:26

PrinsEdje80

Holographic, not grated...

Topicstarter
Okee, ik ben nu al een hele dag in gevecht met arrays (handige dingen, maar lastig af en toe).
Wat is het geval: ik wil graag het volgende maken:
C++:
1
2
3
4
5
double edge = 10.;    //size of the edge of the squares of the grid in pix
unsigned nx = static_cast<unsigned>(floor(8352./edge)+1); //de getallen zijn ook weer variabelen
unsigned ny = static_cast<unsigned>(floor(7860./edge)+1); //maar zijn nu ff ingevuld..
unsigned nframes = 6;
vector<fline>square[nframes][nx][ny]; //waarbij fline een class is, die goed werkt! is getest

Als ik met deze code in de .cc file compileer, gaat dit perfect! Alleen wanneer ik het programma draai, dan knalt hij op het moment van de declaratie van square eruit... En het stomme is, wanneer ik edge naar 17 verhoog, dan werkt het perfect!!! En het is echt alleen afhankelijk van de grootte van het dimensionele gedeelte van square (dus [nframes][nx][ny]).
Nu de volgende vragen (en ik hoop dat jullie ze allemaal beantwoorden):
• wat is de reden dat een segmentation fault komt op regel 5?
• hoe kan ik het oplossen, want ik het echt die vector-array nodig van 6 bij 836 bij 787
• als het systeem verkeerd is opgezet: hoe te verbeteren? (Het idee is dat ik dus een 6 bij 836 bij 787 bij variabele grootte array heb. Dit variabele grootte heb ik dus opgelost door een vector als type te gebruiken.)

[specs van systeem]
Solaris machine met 8 GB RAM en 14 GB swap
Unix.
[/specs]

[ Voor 5% gewijzigd door PrinsEdje80 op 23-09-2003 08:09 . Reden: specs added ]

Used to be Down Under... Foto gallery


  • justmental
  • Registratie: April 2000
  • Niet online

justmental

my heart, the beat

Ik weet niet hoeveel bytes een element uit je array is, maar 6*836*787 is wel 3.947.592.
Dus 3.947.592 * (x bytes element + x overhead?) = heel veel memory.

Who is John Galt?


  • PrinsEdje80
  • Registratie: Oktober 2001
  • Laatst online: 01-01 15:26

PrinsEdje80

Holographic, not grated...

Topicstarter
Snap ik, daarom werk ik ook op een computer met 4 GB RAM.
C++:
1
cout << sizeof(fline) << endl;

geeft 88.

Used to be Down Under... Foto gallery


  • MPAnnihilator
  • Registratie: Juni 2002
  • Laatst online: 14-04 20:25
En Volgens je specs maar 128 mb memory :p , Justmental zou wel eens gelijk kunnen hebben :p

En Windows XP erop 8)7 , die alles al opvreet waarschijnlijk.

[ Voor 27% gewijzigd door MPAnnihilator op 23-09-2003 08:04 ]

Mijn Specs


  • ETA
  • Registratie: Juni 2003
  • Laatst online: 27-04 16:10

ETA

stack overflow?

int x[nframes][nx][ny]; is op de stack

int *** x = new int[nframes][nx][ny] is op de heap

  • PrinsEdje80
  • Registratie: Oktober 2001
  • Laatst online: 01-01 15:26

PrinsEdje80

Holographic, not grated...

Topicstarter
Euh, mijn specs doen er nu ff niet toe, want ik werk op de universiteit... 4 GB RAM solaris machines...
Kunnen jullie nu aub mijn vragen beantwoorden?!?
stack overflow?

int x[nframes][nx][ny]; is op de stack

int *** x = new int[nframes][nx][ny] is op de heap
in simpele taal?!? (is geen int btw, maar fline = class)

[ Voor 39% gewijzigd door PrinsEdje80 op 23-09-2003 08:06 ]

Used to be Down Under... Foto gallery


  • justmental
  • Registratie: April 2000
  • Niet online

justmental

my heart, the beat

Het lijkt me sterk dat je die 4 Gb mag gebruiken voor 1 object, er zullen wel grenzen zijn voor elk object.
Met een korte berekening (*10/17) lijkt dit op 256 Mb te liggen.

Who is John Galt?


  • PrinsEdje80
  • Registratie: Oktober 2001
  • Laatst online: 01-01 15:26

PrinsEdje80

Holographic, not grated...

Topicstarter
Maar als ik bijvoorbeeld het volgende doe:
C++:
1
2
3
4
vector<fline>square1[nx][ny];
vector<fline>square2[nx][ny];
vector<fline>square3[nx][ny];
//etc, totdat ik er 6 heb...

dan flipt hij op dezelfde wijze!

Used to be Down Under... Foto gallery


  • Sebazztiaan
  • Registratie: Februari 2002
  • Laatst online: 21-04 16:53

Sebazztiaan

sebas!

De vector klasse kan alleen werken met een integer aantal. Door in de aanroep een punt te zetten maak je er een float van en de vectorklasse kan niet met een float werken? Probeer het eens zonder de punt.

C++:
1
2
3
double edge = 10;     
unsigned nx = static_cast<unsigned>(floor(8352/edge)+1); 
unsigned ny = static_cast<unsigned>(floor(7860/edge)+1);

Verwijderd

Ik zit ook eerder te denken aan een stack overflow...

De size van de array is
88 x 6 x 836 x 787 = 347.388.096

Is wel heeeel veel !!

Het zou ook nog jouw object kunnen zijn!!
Is de constructor van fline wel goed?

Verwijderd

Ik heb nog effe zitten nadenken, naar je hebt met onderstaande:

vector<fline>square[nframes][nx][ny];

Een meer-dimensionale array met meer dan 3 miljoen vectoren van fline objecten!?!
Weet je zeker dat dit de bedoeling is?

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 23:38
Probeer die variabelen eens op de heap te alloceren, geeft ie dan ook die fout ?

Verder, maar dat is denk ik wat persoonlijk, vind ik dat software die gebruik maakt van arrays met meer dan 2 dimensies vaak ongelooflijk lastig te doorgronden is.

Jij hebt met die declatie in principe al 4 dimensies ( die van de vector meegenomen ).

Is het niet verstandig om de logica voor het pushen en poppen van de waarden in je array in een object te wrappen ?

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • demonite
  • Registratie: April 2000
  • Laatst online: 31-03 13:43

demonite

the way is up

test het eens met een malloc.

vooral aangezien met edge=17 wel lukt.. lijkt erop dat je tegen een limiet aanknalt.


btw, domme vraag misschien... Je hebt dan wel een Sun met 8 GB geheugen... maar compileer je in 64 bits mode ? anders heb je daar natuurlijk ook niets aan.

[ Voor 103% gewijzigd door demonite op 23-09-2003 10:19 ]


  • Pooh
  • Registratie: April 2001
  • Niet online

Pooh

Lees eens een boek

...want ik heb echt die vector-array nodig van 6 bij 836 bij 787...
Heb je die ook echt in 't geheugen nodig? Kun je niet een groot deel op disk laten staan, en je operaties uitvoeren op een subset ervan?

Misschien moet je eens vertellen wat je precies aan 't doen bent.

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 04:38
Ik zou aanraden om eerst uit te zoeken of sprake is van een stack overflow, door de dimensies van je array te verkleinen of de array op de heap te allocere (zoals oa. farlane suggereerde); als dat wel werkt, dan is dat vermoeden redelijk bevestigd.

Vervolgens vrees ik dat je je programma aan zult moeten passen, zodat je het grote blok geheugen op de heap alloceert of als globale variabele declareert (of doe je dat nu al?). In principe kun je wel de stack space opvoeren (onder BSD doe ik dat met "ld --stack", dacht ik, maar dat zou onder Solaris anders kunnen zijn), maar zoals gamecreature al voorrekende, heb je wel uitzonderlijk veel ruimte op de stack nodig (in de orde van 512 MB, waar in de orde van 1 MB gebruikelijk is!). Aan de andere kant: voor een kritische toepassing op een machine met 8 GB alleen al aan RAM is het misschien acceptabel.

Overigens denk ik niet dat er een limiet is aan de grootte van een individueel 'object', zoals justmental suggereert. Ten eerste omdat ik op assembly code nivo geen scenario zou kunnen verzinnen waarin de grootte van het object relevant zou zijn (uitgaande van een flat memory model waarmee de specifieke indeling van memory pages op OS-nivo irrelevant is) en ten tweede omdat je geen echte grote 'objecten' hebt maar alleen een array met veel objecten erin; een array is gewoon een dom stuk groot geheugen en ik zou wederom niet weten waarom aan de grootte daarvan een limiet gesteld zou moeten worden. Het enige praktische probleem wat me reeel lijkt is het gebruik van 32-bits instructies, maar zelfs dan zou je verwachten dat je toch wel 4GB kunt addressen (en toch wel de helft ter beschikking van je applicatie kunt hebben).

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 28-04 14:41

.oisyn

Moderator Devschuur®

Demotivational Speaker

PrinsEdje80 schreef op 23 september 2003 @ 08:07:
Maar als ik bijvoorbeeld het volgende doe:
C++:
1
2
3
4
vector<fline>square1[nx][ny];
vector<fline>square2[nx][ny];
vector<fline>square3[nx][ny];
//etc, totdat ik er 6 heb...

dan flipt hij op dezelfde wijze!
je maakt nu per square nx*ny vectors aan... (je krijgt dus een 3D array uiteindelijk) is dat sowieso wel de bedoeling?
Bovendien moeten de array-groottes een compile-time known constant zijn, en dat zijn ze dus niet. Sommige compilers zoals gcc kunnen dit wel, maar het is eigenlijk niet correcte c++

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • ETA
  • Registratie: Juni 2003
  • Laatst online: 27-04 16:10

ETA

PrinsEdje80 schreef op 23 September 2003 @ 08:05:
Euh, mijn specs doen er nu ff niet toe, want ik werk op de universiteit... 4 GB RAM solaris machines...
Kunnen jullie nu aub mijn vragen beantwoorden?!?


[...]

in simpele taal?!? (is geen int btw, maar fline = class)
Stomme vraag misschien, maar heb jij wel enige software ervaring?

Zoals reeds ook door andere gemeld, is het een gigantisch blok voor de stack.
Terwijl de stack bedoeld is voor function-calls(backtracing) + parameters en voor kleine tijdelijke data, en de heap voor dit soort gigantische (of ook kleinere) blokken data.

Een reden waarom zo'n groot blok data niet gealloceerd zou kunnen wordem,
is dat er al een hele hoop grote blokken zijn gealloceerd, en een aantal daarvan ge-delete.
Het nieuwe blok data zou dan niet meer als continu-block binnen jouw process gemapped worden.
Oftewel je process memory space is gefragmenteerd,
maar daar zal je niet ZO gauw tegen aan lopen naar mijn idee

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 04:38
eta76 schreef op 23 september 2003 @ 12:54:
Een reden waarom zo'n groot blok data niet gealloceerd zou kunnen wordem,
is dat er al een hele hoop grote blokken zijn gealloceerd, en een aantal daarvan ge-delete.
Dat is bij stack-allocatie eigenlijk niet aan de orde; je hebt je stack space namelijk al gereserveerd (als het goed is).

edit:
Hieronder stonden een aantal nogal onzinnige opmerkingen. :)
Het nieuwe blok data zou dan niet meer als continu-block binnen jouw process gemapped worden. Oftewel je process memory space is gefragmenteerd, maar daar zal je niet ZO gauw tegen aan lopen naar mijn idee
Dat kan bij heap allocatie wel optreden, inderdaad, maar als het goed is handelt je memory manager dat af door de heap te compacten. Uiteraard kan je alle beschikbare memory pages wel gewoon op een opvolgend stuk geheugen mappen (daar heb je tenslote je MMU voor!). Fragmentatie van de heap kan, volgens mij, dus hooguit performance problemen opleveren, maar niet resulteren in het falen van een allocatie. Een en ander is natuurlijk een beetje afhankelijk van de gebruikte memory manager.

[ Voor 5% gewijzigd door Soultaker op 23-09-2003 20:39 ]


  • ETA
  • Registratie: Juni 2003
  • Laatst online: 27-04 16:10

ETA

1)
ik bedoelde ook niet een gefragmenteerde stackspace, dat is onmogelijk.
Ik bedoelde dat wanneer je een 'new' zou doen dat in het ergste geval
geen ruimte gealloceerd zou worden om deze reden.


2)
De oplossing die jij aangeeft voor een ge-fragmenteerde heap, wordt op deze manier
wel door het operating systeem gedaan.

Maar de memorymanager van het operating systeem, mag nooit zomaar blokken data in de userspace gaan verplaatsen. Alle pointers die je dan hebt zouden ongeldig worden.
en je app zou zeker crashen.
Een gefragmenteerde userspace is enkel met een hele luxe c-runtime op te lossen en werk van de programmeur, om na een her-lokatie zijn pointers te versen....
Oftewel dit zal nooit gaan gebeuren.

E.

[ Voor 4% gewijzigd door ETA op 23-09-2003 19:14 ]


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 04:38
eta76 schreef op 23 September 2003 @ 17:14:
De oplossing die jij aangeeft voor een ge-fragmenteerde heap, wordt op deze manier wel door het operating systeem gedaan.

Maar de memorymanager van het operating systeem, mag nooit zomaar blokken data in de userspace gaan verplaatsen. Alle pointers die je dan hebt zouden ongeldig worden.
Inderdaad mag dat natuurlijk niet. Dat is echter geen probleem; het besturingssysteem kan nooit last van fragmentatie hebben, omdat 'ie memory pages naar believen kan mappen op de adresruimte van het proces.
Een gefragmenteerde userspace is enkel met een hele luxe c-runtime op te lossen en werk van de programmeur, om na een her-lokatie zijn pointers te versen.... Oftewel dit zal nooit gaan gebeuren.
Hmm, daar had ik helemaal niet bij nagedacht. Beetje onzinnige reactie van mij, achteraf gezien. :/ Je hebt dus gelijk: heap fragmentatie is wel degelijk een probleem voor de memory manager.

  • PrinsEdje80
  • Registratie: Oktober 2001
  • Laatst online: 01-01 15:26

PrinsEdje80

Holographic, not grated...

Topicstarter
Dank voor de vele tips. Er is een aantal zaken dat ik niet begrijp. Hopelijk kunnen jullie me dat uitleggen. Maar eerst zal ik uitleggen wat ik hiermee wil.

Wat heb ik?
Ik heb 6 tekstbestanden met daarin gegevens van objecten (en dat zijn geen computerobjecten, maar Sterrenkundige objecten), zoals x- en y-coordinaat, flux, fluxerror, etc. Nu zijn dit gegevens in verschillende filters, nl. 2 breedband-filters (B en R), een mediumband-filter en 3 narrowband-filters. De medium- en narrowband-filters zitten in een OH-window in de atmosfeer, waar de atmosfeer transparant is. En dit komt precies overeen met Ly-alpha melkwegstelsels op een roodverschuiving van z = 5.7.
Wat wil ik er mee?
Nu wil ik die gegevens gaan combineren op x en y. Dus een object in R op x=100.5 en y=101.4 moet gekoppeld worden aan een object in B op x=100.1 en y=101.5.
Hoe wilde ik dit doen?
Maak een array van 6 (= aantal banden) bij x-grootte ccd/10 bij y-grootte ccd/10 en daarin een variabele hoeveelheid van objecten, die in dat stukje van de ccd (groottte ~8k x 8k) liggen.
Noem even de locatie waarin een object ligt (i,j), dan controleer in al de andere banden in (i-1,j-1), (i-1, j), (i-1,j+1), etc.. (i+1, j+1) om te kijken welk object matched (bepaalde voorwaarden...)
Waarom?
Er is een andere optie, maar dat is elke keer door de hele lijst heen gaan en elk object aan de voorgaande matchen en kijken welke het beste past (tijdrovend!!!)

Dit is een beetje waar het over gaat. Het gaat er mij om dat ik mijn methode kan implementeren. Het zal niet allemaal netjes zijn, zoals ik het wil, zo zij het...
Als jullie me kunnen helpen: graag! (Graag niet ingaan op het Sterrenkundige deel op het forum, via de mail: zeker weten!!)

Mijn programmeer ervaring is een cursus c++ van Frank Brokken (mocht het sommige mensen wat zeggen; vrij goed niveau, alleen niets over architecturen, stacks, buffers, etc.).

Nu nog een vraagje van mijn kant:
• Alloceren op de heap: is dat mbv malloc?!? Zo ja, wat is de c++ variant om dat netjes te doen? (Het is waarschijnlijk new. Kunnen jullie een hint geven hoe ik dit moet implementeren, alsjeblieft!) (Alhoewel eta76 in zijn stack overflow een hele goeie hint geeft... ga ik proberen!)

Misschien is het van mijn kant uit naar jullie duidelijker. Ik ga ff spelen met new en dan horen jullie het wel. Thnx a lot!! (Een nacht rust doet ook wonderen ;))

Used to be Down Under... Foto gallery


  • PrinsEdje80
  • Registratie: Oktober 2001
  • Laatst online: 01-01 15:26

PrinsEdje80

Holographic, not grated...

Topicstarter
Okee, ik doe nu dit
C++:
1
2
3
4
5
6
7
8
9
10
11
//THIS SHOULD DO THE TRICK
cout << "Starting memory allocation... ";
vector<fline> ***square;
square = new vector<fline>**[nframes];
for(unsigned i=0;i<nframes;i++)
{
  square[i] = new vector<fline>*[nx];
  for(unsigned j=0;j<nx;j++)
    square[i][j] = new vector<fline>[ny];
}
cout << "\33[32m success!\33[0m" << endl;
ter vervanging van
C++:
1
vector<fline>square[nframes][nx][ny];
en het werkt! Dank voor de tips...

En op z'n top geeft top een geheugen gebruik van 100 MB aan.

Nu weet ik van de cursus dat ik ook mijn programma netjes delete moet gaan uitvoeren... *zucht* ;)
edit:

Toch ff nog de correcte(?) delete statements toevoegen...

C++:
1
2
3
4
5
6
7
8
9
10
//Cleaning out the memory rubbish!
cout << "Starting memory deallocation... ";
for(unsigned i=0;i<nframes;i++)
{
  for(unsigned j=0;j<nx;j++)
    delete[] square[i][j];
  delete[] square[i];
}
delete[] square;
cout << "\33[32m success!\33[0m" << endl;

[ Voor 38% gewijzigd door PrinsEdje80 op 24-09-2003 02:49 ]

Used to be Down Under... Foto gallery

Pagina: 1