View Single Post
Old 29-03-2006, 09:25   #10
sottovento
Senior Member
 
L'Avatar di sottovento
 
Iscritto dal: Nov 2005
Città: Texas
Messaggi: 1722
Quote:
Originariamente inviato da andbin
Uff .... certo! Questo è vero, in generale, ma solo se il compilatore conosce a priori le caratteristiche dell'array. Per un array a 1 dimensione le due espressioni che hai riportato sopra sono sempre equivalenti.
Per un array a 2 dimensioni, la cosa è un po' diversa. Il compilatore deve sapere a priori quante colonne ha l'array.
double arr[3][4];

double tmp = *(arr + i*4 + j);
e
double tmp = arr[i][j];
Sono certamente equivalenti.

Il problema di vermaccio era quello di voler passare alla funzione un array bidimensionale di dimensione arbitraria (quindi la funzione non deve conoscere a priori le dimensioni).

In questo caso l'unica possibilità è quella di passare un semplice puntatore double *arr alla funzione (passando separatamente alla funzione anche le due dimensioni, ovviamente!) e fare "a mano" l'aritmetica dei puntatori per accedere alla cella dell'array.

Avendo un semplice puntatore, NON puoi fare arr[i][j], perché il compilatore non saprebbe quante colonne ha l'array!!!!

Ah ... i puntatori ...
Scusate, non voglio certo far nascere un caso su un problema del genere.
Comunque, se nella dichiarazione della procedura dichiari

int procedura (double *vect)

e poi intendi usarlo come array (anche bidimensionale), invece che scrivere
elemento = *(vect + i * DIM_X + h);
puoi sempre e comunque scrivere
elemento = vect[i * DIM_X + h];

in entrambi i casi, la gestione della bidimensionalita' della matrice te la gestisci.
Tutto qui, volevo solo dire che era, appunto, un problema di leggibilita'. E' chiaro che non c'e' un motivo oggettivo per preferire una scrittura rispetto all'altra.

Ribadisco anche l'altra osservazione, per vermaccio: ti conviene controllare la conformabilita' delle matrici prima di fare l'operazione. Non e' una cosa secondaria, soprattutto quando gestisci "a mano" la bidimensionalita' delle matrici.

Per quanto riguardava l'osservazione relativa all'ottimizzazione del codice, si tratta di un'ottimizzazione piuttosto ridotta: ovviamente non cambia l'ordine di grandezza del problema (che rimane O(n^3)).

L'ottimizzazione che volevo proporre e' in questo senso: come detto prima, le due scritture sono equivalenti. Quindi vet[i * dim_x + h] == *(vet + dim_x + h). Entrambi genereranno lo stesso numero di operazioni.
Infatti, i compilatori (praticamente tutti e su tutte le piattaforme), carichera' in un registro il valore "base" del vettore, calcolera' l'indice (dato dalla tua formula) e poi moltiplica il tuo indice per la dimensione del tipo base.
Quindi se il tuo tipo double, per esempio, ha dimensione 8 byte, il codice che e' stato scritto, per accedere all'elemento che vuoi:
- carica in un registro (chiamiamolo r_base) l'indirizzo di vect;
- valuta attraverso un parser l'espressione i * dim_x + h e mette il risultato in un registro, chiamiamolo r_index;
- moltiplica il contenuto di r_index per 8;
- somma il contenuto di r_index con r_base e lo pone, diciamo in r_result;

Con r_result puoi accedere all'elemento corretto.

E' chiaro che hai dei puntatori, e li puoi usare per "scorrere" le matrici: li inizializzi all'indirizzo base dei vettori. Poi uno lo incrementi di una unita', mentre l'altro gli sommi direttamente dimx. In questo modo riduci le operazioni sopra riportate.
C'e' da notare che molti processori hanno una istruzione speciale di "leggi ed incrementa" che i compilatori non mancano di utilizzare, pertanto l'istruzione
*p++
viene risolta con una sola istruzione.

Questo e' un tipico caso in cui l'uso dei puntatori puo' portare ad un aumento delle prestazioni

High Flying
Sottovento
sottovento è offline   Rispondi citando il messaggio o parte di esso