PDA

View Full Version : [c] come allocare un vettore o una matrice di grandi dimensioni?


swarzy85
26-07-2010, 08:11
Ciao a tutti,

ho un problema con l'allocazione di una matrice a 4 dimensioni che mi serve per contenere informazioni rilevanti in campo bioinformatico.
La prima versione "ridotta" del programma che sto sviluppando opera su una matrice iniziale di dimensioni 100x1000.
La matrice a 4 dimensioni che deve derivarne deve essere di dimensione 100x100x100x27.

Se provo ad allocarla dinamicamente, mi viene restituito un errore di "stack overflow". Se, invece, provo ad allocarla con la malloc, son costretto poi a scorrerla in modo "ordinato" visto che devo implementare una lista.
Ne deriva che, così facendo, non potrei effettuare un accesso puntuale al dato.
Cosa mi consigliate di fare?

Avevo anche pensato di creare un file e scrivere in modo ordinato gli elementi per poi leggerli o modificarli specificando degli offset.

Che ne pensate? Staticamente, ovviamente, non esiste un modo per allocare una matrice di queste dimensioni, no?

Grazie anticipatamente
Alberto

Teo@Unix
26-07-2010, 11:30
Se provo ad allocarla dinamicamente, mi viene restituito un errore di "stack overflow". Se, invece, provo ad allocarla con la malloc, son costretto poi a scorrerla in modo "ordinato" visto che devo implementare una lista.

cosa intendi per allocazione dinamica? Perchè malloc() è una delle funzioni per l'allocazione dinamica...

comunque hai provato a modificare la dimensione dello stack con le syscall? Io stò dando per scontato che sei su linux.... :)

tuccio`
26-07-2010, 12:44
probabilmente è troppo grande per lo stack, ma non ho capito il problema della matrice allocata nello heap

come stai allocando la matrice dinamicamente?

swarzy85
26-07-2010, 15:12
cosa intendi per allocazione dinamica? Perchè malloc() è una delle funzioni per l'allocazione dinamica...

comunque hai provato a modificare la dimensione dello stack con le syscall? Io stò dando per scontato che sei su linux.... :)

Sono sotto Windows Vista (da stasera sarò su Seven)...sotto Linux non avrei lo stesso problema? Potrei provare con Ubuntu... :)

Comunque se dichiaro in maniera statica la matrice con:

prob_tre_geni [N_PROBES][N_PROBES][N_PROBES][QUARTA_DIM]

dove:
#define N_PROBES 100
#define N_IBRID 1000
#define N_DISCR 3
#define TERZA_DIM 9
#define QUARTA_DIM 27

Mi da errore nello stack di sistema a runtime.

Se invece effettuo una dichiarazione di questo tipo:

struct matrice_quattro
{
int elemento;
struct matrice_quattro *next;
};
struct matrice_quattro *prob_tre_geni;

E successivamente alloco dinamicamente la matrice con:

prob_tre_geni = (struct matrice_quattro*) malloc (sizeof (struct matrice_quattro));

/* Inizializzazione vettore probabilità tre geni */
for (i = 0; i < N_PROBES*N_PROBES*N_PROBES*QUARTA_DIM; i++)
{
prob_tre_geni->elemento = 0;
prob_tre_geni->next = malloc (sizeof (struct matrice_quattro));
}

La matrice viene allocata ma così è un gran casino perchè mi scordo un accesso puntuale ad un dato.

Chiedo lumi :)

Grazie mille


P.S. non saprei come accrescere la dimensione dello stack...in teoria una matrice di circa 27.000.000 di interi non dovrebbe avere una dimensione spropositata e invece a runtime mi occupa circa 2.2GB :eek:

Isildur84
26-07-2010, 15:25
Hai provato l'allocazione dinamica del vettore?


int * matrice = malloc(sizeof(int) * NVALORI);


Questo ovviamente per ogni dimensione della matrice.

Ovviamente "matrice" non dovrebbe essere un int * ma un int **** (almeno così mi sembra).

swarzy85
26-07-2010, 16:06
Ma la matrice così comunque la alloca...il problema è che poi non potrei accedere in maniera puntuale ai singoli campi, no?
Sbaglio qualcosa nelle mie considerazioni?

Isildur84
26-07-2010, 16:36
Se tu la allochi nel modo che ti ho consigliato io (hai bisogno di 3 cicli for), l'accesso è puntuale, in quanto puntatori e vettori in C sono "intercambiabili".
Il tuo metodo della lista invece non permette l'accesso puntuale.

tuccio`
26-07-2010, 18:19
Ma la matrice così comunque la alloca...il problema è che poi non potrei accedere in maniera puntuale ai singoli campi, no?
Sbaglio qualcosa nelle mie considerazioni?per poter scrivere, ad esempio, matrix[0][2][99][13]

devi usare un void****

ad esempio:


int ****matrix = malloc(sizeof(int***) * 100);
int i;
for (i = 0; i < 100; i++) {
int j;
matrix[i] = malloc(sizeof(int**) * 100);
for (j = 0; j < 100; j++) {
int k;
matrix[i][j] = malloc(sizeof(int*) * 100);
for (k = 0; k < 100; k++)
matrix[i][j][k] = malloc(sizeof(int) * 27);
}
}

DoubleAJ
27-07-2010, 00:36
in teoria una matrice di circa 27.000.000 di interi non dovrebbe avere una dimensione spropositata e invece a runtime mi occupa circa 2.2GB :eek:

Se al posto di una lista ti allochi una matrice inoltre ti risparmi esattamente la metà dello spazio in memoria, visto che non hai bisogno di un puntatore per ogni elemento.

malocchio
27-07-2010, 02:30
Lascia stare le liste.

Attento che stai dichiarando la tua "matrice" all'interno di un metodo e di conseguenza essa viene temporaneamente allocata sullo stack (BRUTTA cosa).

Se la matrice deve avere visibilità globale, sposta la sua dichiarazione fuori dal metodo. In quel modo avrai uno spazio di memoria allocato staticamente all'avvio dell'eseguibile.

cionci
27-07-2010, 10:07
Se la matrice ha dimensione prefissata io cercherei una soluzione un po' più bruta, ma funzionale:

int * matrix = (int *)malloc(N_PROBES * N_PROBES * N_PROBES * QUARTA_DIM * sizeof(int));

Poi provvederei a mettere a disposizione una macro per l'accesso alla matrice:

#define matrix_elem(a, b, c, d) (matrix[a*N_PROBES + b*N_PROBES + c*N_PROBS + d])

In alternativa potresti usare un setter ed un getter con un bound check:

inline int get_elem(matrix m, int a, int b, int c, int d)
{
#ifdef _DEBUG
check_bound(a,b,c,d);
#endif
return matrix[a*N_PROBES + b*N_PROBES + c*N_PROBS + d];
}

inline int set_elem(matrix m, int a, int b, int c, int d, int value)
{
#ifdef _DEBUG
check_bound(a,b,c,d);
#endif
matrix[a*N_PROBES + b*N_PROBES + c*N_PROBS + d] = value;
}
In un codice che lavora su 4 indici di una matrice è secondo me di fondamentale importanza avere un controllo sugli indici.
Il controllo sugli indici volendo si potrebbe effettuare anche nella macro ;)

cionci
27-07-2010, 10:09
Se la matrice deve avere visibilità globale, sposta la sua dichiarazione fuori dal metodo. In quel modo avrai uno spazio di memoria allocato staticamente all'avvio dell'eseguibile.
Cioè consigli di allocare una variabile globale ?
Se la alloca dinamicamente è solo il puntatore che risiede nello stack.

malocchio
28-07-2010, 00:57
Cioè consigli di allocare una variabile globale ?
Se la alloca dinamicamente è solo il puntatore che risiede nello stack.

Sì, l'allocazione dinamica è la cosa più indicata, ma a voler essere non troppo pignoli e per aggirare la "complessità" di una allocazione dinamica (con puntatori, inizializzazioni, ecc.) io ho proposto l'all. statica, che di per sé è abbastanza semplice, no? :)

edit: ah, la tua soluzione non mi dispiacerebbe affatto