El rendimiento relativo de std::vector vs std::list vs std::slist?


Para una simple lista enlazada en la que el acceso aleatorio a los elementos de la lista no es un requisito, ¿hay alguna ventaja significativa (rendimiento o no) al usar std::list en lugar de std::vector? Si se requiere un recorrido hacia atrás, ¿sería más eficiente usar std::slist y reverse() la lista antes de iterar sobre sus elementos?

Author: An̲̳̳drew, 2008-10-26

6 answers

Como de costumbre, la mejor respuesta a las preguntas de rendimiento es perfilar ambas implementaciones para su caso de uso y ver cuál es más rápido.

En general, si tiene inserciones en la estructura de datos (que no sean al final), vector puede ser más lento, de lo contrario, en la mayoría de los casos, se espera que vector funcione mejor que list si solo para problemas de localidad de datos, esto significa que si dos elementos que son adyacentes en el conjunto de datos son adyacentes en la memoria, entonces el siguiente elemento ya estar en la caché del procesador y no tendrá que página falla la memoria en la caché.

También tenga en cuenta que la sobrecarga de espacio para un vector es constante (3 punteros) mientras que la sobrecarga de espacio para un list se paga por cada elemento, esto también reduce el número de elementos completos (datos más sobrecarga) que pueden residir en la caché a la vez.

 52
Author: Motti,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:47:36

La estructura de datos predeterminada en la que pensar en C++ es el Vector .

Considere los siguientes puntos...

1] Recorrido:
Los nodos de la lista están dispersos por todas partes en la memoria y, por lo tanto, el recorrido de la lista conduce a errores de caché. Pero el recorrido de los vectores es suave.

2] Inserción y supresión:
El promedio de 50% de los elementos debe ser desplazado cuando se hace eso a un vector, pero cachés son muy buenos en eso! Pero, con listas, necesitas to atravesar hasta el punto de inserción/supresión... otra vez... cache falla! ¡Y sorprendentemente los vectores ganan este caso también!

3] Almacenamiento:
Cuando se utilizan listas, hay 2 punteros por elementos (hacia adelante y hacia atrás) por lo que una Lista es mucho más grande que un vector! Los vectores necesitan solo un poco más de memoria que los elementos reales necesitan.

Usted debe tener una razón para no utilizar un vector.


Referencia:
Aprendí esto en una charla de Lord Bjarne Stroustrup: https://youtu.be/0iWb_qi2-uI?t=2680
 22
Author: Sam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-13 21:43:28

Simplemente no. La lista tiene ventajas sobre el Vector, pero el acceso secuencial no es una de ellas - si eso es todo lo que estás haciendo, entonces un vector es mejor.

Sin embargo.. un vector es más caro para agregar elementos adicionales que una lista, especialmente si está insertando en el medio.

Comprenda cómo se implementan estas colecciones: un vector es una matriz secuencial de datos, una lista es un elemento que contiene los datos y punteros a los siguientes elementos. Una vez que entiendas eso, comprenda por qué las listas son buenas para inserciones y malas para el acceso aleatorio.

(por lo tanto, la iteración inversa de un vector es exactamente lo mismo que para la iteración hacia adelante: el iterador solo resta el tamaño de los elementos de datos cada vez, la lista todavía tiene que saltar al siguiente elemento a través del puntero)

 10
Author: gbjbaanb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-26 13:41:22

Si necesita un recorrido hacia atrás, es poco probable que una slist sea la estructura de datos para usted.

Una lista convencional (doblemente) vinculada le da tiempo constante de inserción y eliminación en cualquier parte de la lista; un vector solo da tiempo constante amortizado de inserción y eliminación al final de la lista. Para un vector, el tiempo de inserción y eliminación es lineal en cualquier lugar que no sea el final. Esta no es toda la historia; también hay factores constantes. Un vector es una estructura de datos más simple que tiene ventajas y desventajas según el contexto.

La mejor manera de entender esto es entender cómo se implementan. Una lista vinculada tiene un puntero siguiente y un puntero anterior para cada elemento. Un vector tiene una matriz de elementos abordados por index. A partir de esto, puede ver que ambos pueden hacer un recorrido eficiente hacia adelante y hacia atrás, mientras que solo un vector puede proporcionar un acceso aleatorio eficiente. También puede ver que la sobrecarga de memoria de una lista vinculada es por elemento, mientras que para el vector es constante. Y también se puede ver por qué el tiempo de inserción es diferente entre las dos estructuras.

 4
Author: janm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-27 01:18:17

Algunos parámetros rigurosos sobre el tema: http://baptiste-wicht.com/posts/2012/12/cpp-benchmark-vector-list-deque.html

Como han señalado otros, el almacenamiento de memoria contigua significa que std::vector es mejor para la mayoría de las cosas. Prácticamente no hay una buena razón para usar std::list, excepto por pequeñas cantidades de datos (donde todos pueden caber en la caché) y/o donde el borrado y la reinserción son frecuentes. Las garantías de complejidad no se relacionan con el rendimiento en el mundo real debido a la diferencia entre las velocidades de caché y memoria principal (200x) y cómo el acceso a memoria contigua afecta el uso de caché. Ver Chandler Carruth (Google) hablar sobre el tema aquí: https://www.youtube.com/watch?v=fHNmRkzxHWs

Y el Diseño Orientado a Datos de Mike Acton hablan aquí: https://www.youtube.com/watch?v=rX0ItVEVjHc

 4
Author: metamorphosis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-15 00:04:34

Consulte esta pregunta para obtener más detalles sobre los costos:
¿Cuáles son las garantías de complejidad de los contenedores estándar

Si tiene una ranura y ahora desea recorrerla en orden inverso, ¿por qué no cambiar el tipo a list everywhere?

 2
Author: Martin York,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:33:27