2009-09-22 18 views
33

Stavo facendo un test delle prestazioni rapido su un blocco di codicestd :: vector reserve() e push_back() è più veloce di resize() e indice di array, perché?

void ConvertToFloat(const std::vector<short>& audioBlock, 
        std::vector<float>& out) 
{ 
    const float rcpShortMax = 1.0f/(float)SHRT_MAX; 
    out.resize(audioBlock.size()); 
    for(size_t i = 0; i < audioBlock.size(); i++) 
    { 
     out[i] = (float)audioBlock[i] * rcpShortMax; 
    } 
} 

ero felice con la velocità fino oltre l'attuazione molto ingenuo originale ci vuole poco più di 1 millisecondo per processare 65.536 campioni audio.

Tuttavia solo per divertimento ho provato la seguente

void ConvertToFloat(const std::vector<short>& audioBlock, 
        std::vector<float>& out) 
{ 
    const float rcpShortMax = 1.0f/(float)SHRT_MAX; 
    out.reserve(audioBlock.size()); 
    for(size_t i = 0; i < audioBlock.size(); i++) 
    { 
     out.push_back((float)audioBlock[i] * rcpShortMax); 
    } 
} 

Ora mi aspettavo questo possa fornire le stesse prestazioni come il codice originale. Tuttavia, improvvisamente il ciclo sta prendendo ora 900usec (cioè è 100usec più veloce rispetto all'altra implementazione).

Qualcuno può spiegare perché questo potrebbe fornire prestazioni migliori? resize() inizializza il vettore appena assegnato dove riserva si alloca ma non costruisce? Questa è l'unica cosa che riesco a pensare.

PS questo è stato testato su un core 2Ghz AMD Turion 64 ML-37.

+0

Un controllo di routine, si sta utilizzando la versione anziché le impostazioni di debug durante la compilazione del codice? – Laserallan

+0

hehehe, sì, stavo usando Release. Era più una domanda su come aiutare il compilatore ad aiutarmi :) – Goz

risposta

52

Il ridimensionamento inizializza il vettore appena assegnato in cui la riserva alloca ma non costruisce?

Sì.

+0

Il riferimento STL di SGI spiega che ridimensiona "inserisce o cancella gli elementi alla fine", mentre riserva solo l'allocazione di memoria. http://www.sgi.com/tech/stl/Vector.html – user7116

+0

Come funziona? malloc? – pyon

+0

Utilizzerà tutto ciò che l'allocatore è impostato per il vettore. – user7116

1
out.resize(audioBlock.size()); 

Da out s' dimensione (= 0) è inferiore audioBlock.size(), elementi aggiuntivi sono creati e aggiunto alla fine del out. Questo crea i nuovi elementi chiamando il costruttore di default.

Reserve alloca solo la memoria.

3

Il primo codice scrive su out[i] che si riduce a begin() + i (ad esempio un'aggiunta). Il secondo codice utilizza push_back, che probabilmente scrive immediatamente su un puntatore noto equivalente a end() (cioè nessuna aggiunta). Probabilmente potresti eseguire la prima esecuzione velocemente quanto la seconda usando gli iteratori piuttosto che l'indice intero.

Edit: anche per chiarire alcune altre osservazioni: il vettore contiene galleggianti, e la costruzione di un galleggiante è effettivamente un no-op (allo stesso modo dichiarando "float f;" non emette il codice, dice solo al compilatore di salva spazio per un galleggiante in pila). Quindi penso che qualsiasi differenza di prestazioni tra resize() e reserve() per un vettore di float non abbia a che fare con la costruzione.

+3

Scusa ma il tuo punto di costruzione non è vero. flottante f = 0.0f; è ovviamente più lento di "float f;". il secondo è un nop il primo non lo è. – Goz

+0

Oh, giusto punto, non sapevo costruire un float assegnato a 0. Vector assegna T() a ciascun elemento durante il ridimensionamento, che è float(), che è 0. Tuttavia, utilizzare gli iteratori invece dell'indice intero potrebbe essere più veloce. – AshleysBrain

3

Resize()

Modifica il contenitore in modo che abbia esattamente n elementi, inserendo elementi di fine o cancellare elementi dalla fine se necessario. Se qualche elemento è inserito, sono copie di t. Se n > a.size(), questa espressione è equivalente a a.insert(a.end(), n - size(), t). Se n < a.size(), è equivalente a a.erase(a.begin() + n, a.end()).

Reserve()

Se n è inferiore o uguale a capacity(), questa chiamata non ha alcun effetto. Altrimenti, è una richiesta per l'allocazione di memoria aggiuntiva.Se la richiesta ha esito positivo, allora capacity() è maggiore o uguale a n; altrimenti, capacity() non è cambiato. In entrambi i casi, size() è invariato.

La memoria verrà riallocata automaticamente se nel vettore sono inseriti più di elementi capacity() - size(). La riallocazione non cambia size(), né modifica i valori di alcun elemento del vettore. Aumenta, tuttavia, capacity()

La prenotazione provoca una riallocazione manuale. Il motivo principale per l'utilizzo di reserve() è l'efficienza: se si conosce la capacità a cui il vettore deve eventualmente crescere, è in genere più efficiente allocare tutta la memoria contemporaneamente anziché fare affidamento sullo schema di riallocazione automatico.

Problemi correlati