2009-10-23 15 views
8

Ho provato 2 cose: (pseudo codice qui sotto)Inizializzazione vettoriale più lenta dell'array ... perché?

int arr[10000]; 
for (int i = 0; i < 10000; i++) 
{ 
    for (int j = 0; j < 10000; j++) 
    { 
     arr[j] = j; 
    } 
} 

e

vector<int> arr(10000); 
for (int i = 0; i < 10000; i++) 
{ 
    for (int j = 0; j < 10000; j++) 
    { 
     arr[j] = j; 
    } 
} 

I corse sia i programmi e contati utilizzando il comando shell "tempo". Il programma 1 viene eseguito in 5 secondi, il programma 2 viene eseguito in 30 secondi. Ho eseguito entrambi i programmi con l'ottimizzazione del compilatore attivata ed entrambi i programmi sono stati eseguiti all'incirca nello stesso tempo (0,38s). Sono confuso da questi risultati. Qualcuno può spiegarmi perché questo sta accadendo?

Grazie!

+2

Vuoi dire che hanno impiegato 5/30 secondi con le ottimizzazioni * disattivate *? – jalf

+0

Ricorda che non sono esattamente equivalenti. Vector assegna di default l'heap, ma l'array è in pila. – GManNickG

+0

Ciao, sì, era parte della mia domanda. Sono stato anche confuso da come hanno eseguito nello stesso tempo dopo l'ottimizzazione. – Aishwar

risposta

16

Per il modello, l'indice viene eseguito con l'operatore []. Con l'ottimizzazione disattivata, questo verrà generalmente generato come una vera chiamata di funzione, aggiungendo un sacco di overhead a qualcosa di semplice come l'iscrizione in un array. Quando attivi l'ottimizzazione, viene generato in linea, rimuovendo l'overhead.

+0

Hey Jerry, grazie per la risposta. Ha senso ora. Credo che con gli array, l'uso di [] non rende la chiamata all'operatore [] poiché è un tipo "naturale" (per mancanza di una parola migliore). Da qui il 5/30. – Aishwar

+0

Destra: per un array integrato, il codice di indice è quasi certamente * sempre * generato in linea. –

+0

E questo sottolinea come la funzione chiamata overhead possa davvero sommarsi. – Crashworks

8

In modalità di debug, le implementazioni di std::vector forniscono un sacco di controllo di runtime per facilità d'uso. Questo controllo non è disponibile per gli array nativi. Ad esempio, in VC2008, se si compila l'esempio vector in modalità di debug, ci sarà range-checkingpari a nel caso di operator[].

5

Se l'implementazione vettoriale non ottimizzata sta eseguendo il controllo dei limiti, ciò spiegherebbe la discrepanza.

+0

++ La mia ipotesi è che tu abbia ragione, ma volevo che lui (o lei) lo scoprisse. –

0

perché quando si scrive vettore arr (10000); crei un oggetto, chiami le sue funzioni ... quando e sarà più lento di quando crei int arr [10000];

0

Negli esempi, la matrice è in pila. L'accesso ai dati nell'array comporta l'accesso ai dati nello stack. È veloce

D'altra parte, mentre lo vector è in pila, i dati per uno std::vector vengono allocati da qualche altra parte (per impostazione predefinita è allocato nello heap tramite std::allocator). L'accesso ai dati nello vector implica l'accesso ai dati nell'heap. È molto più lento dell'accesso ai dati nello stack.

Si ottiene qualcosa per la penalizzazione delle prestazioni, però. std::vector è coltivabile, mentre un array normale non lo è. Inoltre, la dimensione di un std::vector non deve essere costante di tempo di compilazione, mentre la dimensione di un array nello stack. Una matrice allocata su heap (tramite operator new[]) non deve essere una costante in fase di compilazione. Se confronti un array assegnato all'heap con un std::vector, troverai che le prestazioni sono molto più vicine.

int* arr = new int[10000]; 
for (int i = 0; i < 10000; i++) 
{ 
    for (int j = 0; j < 10000; j++) 
    { 
     arr[j] = j; 
    } 
} 

delete[] arr; // std::vector does this for you 
4

Queste sono buone risposte, ma c'è un modo rapido per scoprirlo da soli.

Stai vedendo una differenza di prestazioni 6 a 1, giusto? Basta eseguire quello lento e premere il pulsante "pausa". Quindi guarda lo stack delle chiamate. La probabilità è 5 su 6 (83%) che vedrai esattamente come si spendono quei 25 secondi in più. Fatelo diverse volte per ottenere tutte le informazioni che desiderate.

Per il caso ottimizzato, fare lo stesso con il programma 1. Poiché è 13 volte più lento del programma ottimizzato, vedrete il motivo per cui su ogni "pausa", con probabilità 12/13 = 92%.

Questa è un'applicazione di this technique.

+1

Ho visto esplodere molte menti degli sviluppatori quando ho visto per la prima volta la buona tecnica di pausa, specialmente quando non la comprano e passano altre ore server impostando una sessione di profilazione completa solo per scoprire che la "pausa" ha già avuto successo. – DanO

+0

@DanO: Sì. Sto solo cercando di ottenere la parola. Non c'è motivo per la gente di non saperlo. –

+0

Hey Mike, grazie per la risposta. Mi piacerebbe provarlo, ma sto usando un ambiente a riga di comando e gcc per compilare i miei programmi (sono nuovo in questo ambiente). C'è un modo per metterlo in pausa e vedere la traccia dello stack lì? Grazie :) – Aishwar

Problemi correlati