2011-10-31 27 views
5

¿Debería preocuparme por la fragmentación de memoria con std :: vector? Si es así, ¿hay formas de ayudar a prevenirlo? No siempre predigo que mis programas se ejecuten en una PC, también se pueden ejecutar en dispositivos integrados/consolas de juegos, por lo que no siempre podré confiar en la memoria virtual.¿Debería preocuparme por la fragmentación de memoria con std :: vector?

Por otra parte, creo que sería más eficiente utilizar una matriz de tamaño dinámico en lugar de una matriz estática, por lo que la memoria solo se asignaría si fuera necesario. También simplificaría el proceso de diseño de mis programas. ¿Hay formas de lograr esto de manera eficiente?

¡Gracias por cualquier consejo!

+1

Hay un parámetro de plantilla de asignador opcional que puede especificar para obtener un control más estricto sobre cómo se realizan las asignaciones de memoria. –

Respuesta

10

La respuesta a sus preocupaciones puede ser std::deque. Le da una interfaz similar a la de std::vector, pero funciona mejor con la memoria fragmentada, ya que asigna varias matrices pequeñas en lugar de una grande. De hecho, es menos eficiente que std::vector en algunos aspectos, pero para su caso puede ser una buena solución de compromiso.

+0

¿puede ubicar una fuente para las reclamaciones que realiza? preferiblemente una referencia estándar? ** La actualización ** encontró un inicio yo mismo: http://www.gotw.ca/gotw/054.htm – sehe

+1

@sehe: me temo que el estándar tiende a no hacer cumplir las implementaciones para permitir optimizaciones desconocidas. Ni siquiera obliga a implementar 'std :: vector' utilizando una matriz interna, aunque dudo mucho que alguien pueda implementarlo de otra manera. Pero usualmente 'std :: deque' se implementa usando matrices pequeñas. Ver http://www.cplusplus.com/reference/stl/deque/, por ejemplo, para una breve discusión independiente de la biblioteca. – Gorpik

1

No, std :: vector garantiza el almacenamiento contiguo. Puede usar vector :: reserve() para evitar reasignaciones a medida que aumenta el tamaño del vector.

+3

Es precisamente por eso que necesita preocuparse por la fragmentación de la memoria. Si lo nuevo no puede encontrar, por ej. un bloque contiguo 4k de repuesto no puede asignar un vector de 1000 ints. –

+1

¿cómo se relacionaría eso con la fragmentación del montón? La fragmentación del montón no depende del diseño de una clase. Depende de los patrones de asignación y la política/algoritmos de asignación. – sehe

+0

Considero que "preocuparse por la fragmentación de la memoria" significa "preocuparse de que la memoria a la que se accede esté fragmentada", porque acceder a la memoria no contigua significa que probablemente no obtenga los beneficios de rendimiento de la recuperación previa y similares. – bames53

2

Siempre debe preocuparse por el rendimiento y la eficiencia cuando el perfilador dice que por lo (puede ser que perfilador, pero hay que 'medida', no adivine).

cosas que puede hacer:

  1. previamente la capacidad en:

    std::vector<int> x(1000); // size() is 1000 
    
    std::vector<int> y; 
    y.reserve(1000); // size() is 0, capacity is 1000 
    
  2. utilizar un asignador de costumbre

La primera opción es claramente la victoria rápida; La segunda opción es más complicada y solo la recomiendo cuando tu perfilador de montón te diga que la fragmentación está causando problemas.

Para perfiles montón, me sugieren

3

std :: vector es sólo tan buena como nueva. Simplemente maneja la asignación de memoria subyacente para usted Un par de cosas que puede hacer, suponiendo que no desea escribir un nuevo nuevo controlador.

Preasigne los vectores o cambie el tamaño() si conoce el tamaño final que tendrán, esto detiene el desperdicio de copias de memoria a medida que crecen.

Si va a volver a utilizar el vector con el mismo tamaño, es mejor guardarlo y rellenarlo que eliminarlo y volver a crearlo.

Generalmente en objetivos incorporados, si conoce los requisitos de memoria, es mejor asignar estáticamente toda la memoria al inicio y dividirla usted mismo, no es como si otro usuario quisiera algo.

5

Si su vector se reasignará muchas veces, entonces sí, puede causar la fragmentación de la memoria. La forma más sencilla de evitar eso sería usando std::vector::reserve() si más o menos sabe qué tan grande puede crecer su matriz.

También puede considerar el uso de std::deque en lugar de vector, por lo que no tendrá ningún problema con la fragmentación de memoria.

Aquí hay un tema en stackoverflow que puede ser interesante para usted: what-is-memory-fragmentation.

2

Una buena manera de minimizar la asignación de memoria repetida y las llamadas de reasignación con std::vector es hacer un uso liberal de std::vector::reserve() si tiene alguna idea de cuántos elementos va a utilizar su vector. Eso preasignará la capacidad e impedirá el cambio de tamaño de la matriz interna que el vector mantiene mientras agrega elementos a través del push_back().

Cuestiones relacionadas