2011-08-19 10 views
5

Per quanto riguarda le prestazioni, è preferibile accedere a un elemento di matrice 'direttamente' più volte o assegnare il suo valore a una variabile e utilizzare tale variabile? Supponendo che farò riferimento al valore più volte nel seguente codice.Accesso diretto a un elemento di matrice direttamente rispetto all'assegnazione a una variabile

Il ragionamento alla base di questa domanda è che l'accesso a un elemento di matrice comporta presumibilmente alcuni costi di elaborazione ogni volta che viene eseguito, senza richiedere spazio aggiuntivo. D'altra parte, la memorizzazione del valore in una variabile elimina questo costo di accesso, ma occupa uno spazio aggiuntivo.

// use a variable to store the value 
Temp = ArrayOfValues(0) 
If Temp > 100 Or Temp < 50 Then 
    Dim Blah = Temp 
    ... 

// reference the array element 'directly' 
If ArrayOfValues(0) > 100 Or ArrayOfValues(0) < 50 Then 
    Dim Blah = ArrayOfValues(0) 
    ... 

So che questo è un esempio banale, ma assumendo stiamo parlando di una scala più grande in uso effettivo (dove il valore si farà riferimento molte volte) A che punto è il compromesso tra lo spazio e il tempo vale la pena di calcolo considerando (se non del tutto)?

+1

Un compilatore di ottimizzazione sta per rendere questo assolutamente discutibile per gli HLL. Se si utilizza l'assembly o si disattivano le ottimizzazioni, i registri sono più veloci della cache, quindi è necessario caricare i valori utilizzati di frequente nei registri il più possibile. In generale, penso che il punto critico tra la pressione del registro e la gerarchia della memoria sia probabilmente una questione empirica. – Patrick87

risposta

2

L'overhead nel consumo di memoria è molto limitato perché per i tipi di riferimento è solo un puntatore (paio di byte) e la maggior parte dei tipi di valore richiede anche solo pochi byte.

Gli array sono strutture molto efficienti nella maggior parte delle lingue. Raggiungere un indice non comporta alcuna ricerca ma solo alcuni calcoli matematici (ogni slot di matrice richiede 4 byte, quindi l'11 ° slot è all'offset 40). Quindi c'è probabilmente un po 'di overhead per il controllo dei limiti. Allocare la memoria per una nuova var locale e liberarla richiede anche un po 'di cicli di CPU. Quindi alla fine dipende anche da quante ricerche di array si eliminano copiando su una var locale.

Il fatto è che hai davvero bisogno di hardware eccezionalmente scadente o di loop davvero grandi perché questo sia davvero importante e se viene eseguito un test decente su di esso. Personalmente scelgo spesso la variabile separata perché trovo che rende il codice più leggibile.

Il vostro esempio è strano btw dal momento che 2 ricerche di matrice prima di creare la var locale :) Questo ha più senso (eliminazione 2 ulteriori ricerche)

Dim blah = ArrayOfValues(0) 
if blah > 100 or blah < 50 then 
... 
2

questo linguaggio è etichettato agnostico, ma io don credono davvero che lo sia. Questo post risponde alla versione C e C++ della domanda.

Un compilatore ottimizzante può occuparsi degli accessi di array "nudi"; in C o C++ non c'è motivo di pensare che il compilatore non ricorderebbe il valore di una locazione di memoria se non ci fossero chiamate in mezzo. Per esempio.

int a = myarray[19]; 
int b = myarray[19] * 5; 
int c = myarray[19]/2; 
int d = myarray[19] + 3; 

Tuttavia, se myarray non è solo definito come int [] ma è in realtà qualcosa "fantasia", in particolare alcuni definito dall'utente tipo contenitore con una funzione operator[]() definita in un'altra unità di traduzione, allora quella funzione deve essere chiamato ogni volta che viene richiesto il valore (poiché la funzione restituisce i dati nella posizione in memoria e la funzione locale non sa che il risultato della funzione è inteso essere costante).

Anche con gli array "naked", tuttavia, se si accede alla stessa cosa più volte per le chiamate di funzione, il compilatore deve presupporre che il valore sia stato modificato (anche se può ricordare l'indirizzo stesso). Per esempio.

int a = myarray[19]; 
NiftyFunction(); 
int b = myarray[19] * 8; 

Non c'è modo che il compilatore può sapere che myarray [19] avranno lo stesso valore prima e dopo la chiamata di funzione.

Quindi, in generale, se si sa che un valore è costante attraverso l'ambito locale, "cache" in una variabile locale. È possibile programmare in difesa e utilizzare le asserzioni per convalidare questa condizione che hai messo sulle cose:

int a = myarray[19]; 
NiftyFunction(); 
assert(myarray[19] == a); 
int b = a * 8; 

Un vantaggio finale è che è molto più facile da controllare i valori in un debugger se non sono sepolti in un array da qualche parte .

+1

+1 per "Questo è codificato linguaggio agnostico, ma non credo davvero che sia." La risposta C# potrebbe essere diversa in certi modi, ma non sono qualificato per offrirla. – ClickRick

Problemi correlati