2009-09-22 7 views
33

que estaba haciendo una prueba de rendimiento rápido en un bloque de códigostd :: vector reserve() y push_back() es más rápido que resize() y el índice de matriz, ¿por qué?

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; 
    } 
} 

que estaba contento con la velocidad a lo largo de la implementación original de muy ingenuo que se necesita un poco más de 1 ms para procesar 65.536 muestras de audio.

Sin embargo sólo por diversión He intentado lo siguiente

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); 
    } 
} 

Ahora que esperaba totalmente esto para dar exactamente el mismo rendimiento que el código original. Sin embargo, de repente, el ciclo ahora toma 900usec (es decir, es 100usec más rápido que la otra implementación).

¿Alguien puede explicar por qué esto daría un mejor rendimiento? ¿resize() inicializa el vector recientemente asignado donde reserva solo asigna pero no construye? Esto es lo único que se me ocurre.

PS esto fue probado en un solo núcleo 2Ghz AMD Turion 64 ML-37.

+0

Una comprobación de rutina, ¿está utilizando la versión en lugar de la configuración de depuración al compilar el código? – Laserallan

+0

jejeje, sí, estaba usando Release. Era más una pregunta sobre ayudar al compilador a ayudarme :) – Goz

Respuesta

52

¿Cambia el tamaño inicializa el vector recientemente asignado donde reserva solo asigna pero no construye?

Sí.

+0

La referencia STL de SGI explica que el tamaño "inserta o borra elementos al final", mientras que la reserva solo hace la asignación de memoria. http://www.sgi.com/tech/stl/Vector.html – user7116

+0

¿Cómo funciona eso? malloc? – pyon

+0

Utilizará lo que el asignador esté configurado para el vector. – user7116

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

Desde out 's tamaño (= 0) es menor que audioBlock.size(), elementos adicionales se crean y adjunta al final de la out. Esto crea los nuevos elementos llamando a su constructor predeterminado.

Reserve solo asigna la memoria.

3

El primer código se escribe en out[i], que se reduce a begin() + i (es decir, una adición). El segundo código usa push_back, que probablemente se escribe inmediatamente en un puntero conocido equivalente a end() (es decir, sin adición). Probablemente puedas hacer la primera carrera tan rápido como la segunda al usar iteradores en lugar de índices enteros.

Editar: también para aclarar algunos otros comentarios: El vector contiene los flotadores, y la construcción de un flotador es efectivamente un no-op (de la misma manera que se declara "flotar f;" no emite código, sólo se indica al compilador que ahorrar espacio para un flotador en la pila). Así que creo que cualquier diferencia de rendimiento entre resize() y reserve() para un vector de flotadores no tiene que ver con la construcción.

+3

Lo siento, pero su punto de construcción no es cierto. flotar f = 0.0f; es obviamente más lento que solo "flotar f". el último ES un nop el primero no lo es. – Goz

+0

Oh, punto justo, no sabía construir un flotador asignado 0. Vector asigna T() a cada elemento al redimensionar, que es float(), que es 0. Aún así, usar iteradores en lugar de índices enteros podría ser más rápido. – AshleysBrain

3

de cambio de tamaño()

Modifica el recipiente de manera que tiene exactamente n elementos, la inserción de elementos en el extremo o borrado de elementos desde el extremo si es necesario. Si se insertan elementos, son copias de t. Si n > a.size(), esta expresión es equivalente a a.insert(a.end(), n - size(), t). Si es n < a.size(), es equivalente a a.erase(a.begin() + n, a.end()).

Reserva()

Si n es menor o igual a capacity(), esta llamada no tiene ningún efecto. De lo contrario, es una solicitud de asignación de memoria adicional.Si la solicitud es exitosa, entonces capacity() es mayor que o igual a n; de lo contrario, capacity() no se modifica. En cualquier caso, size() no se modifica.

La memoria se reasignará automáticamente si se insertan más elementos capacity() - size() en el vector. La reasignación no cambia size(), ni cambia los valores de ningún elemento del vector. Sin embargo, aumenta capacity()

La reserva provoca una reasignación manual. La razón principal para usar reserve() es la eficiencia: si conoce la capacidad a la que su vector debe crecer en el futuro, entonces generalmente es más eficiente asignar esa memoria a la vez en lugar de confiar en el esquema de reasignación automática.

Cuestiones relacionadas