c++ - Alternativa STL
performance debug-build (14)
Realmente odio usar contenedores STL porque hacen que la versión de depuración de mi código se ejecute muy despacio. ¿Qué utilizan otras personas en lugar de STL que tiene un rendimiento razonable para compilaciones de depuración?
Soy un programador de juegos y esto ha sido un problema en muchos de los proyectos en los que he trabajado. Es bastante difícil obtener 60 fps cuando utilizas contenedor STL para todo.
Uso MSVC para la mayor parte de mi trabajo.
¿Qué pasa con la biblioteca de ACE ? Es un marco orientado a objetos de código abierto para software de comunicación concurrente, pero también tiene algunas clases de contenedor.
Apuesto a que su STL utiliza una implementación comprobada para la depuración. Esto es probablemente una buena cosa, ya que atrapará los excesos de iteradores y demás. Si es un gran problema para usted, puede haber un interruptor de compilación para apagarlo. Verifica tus documentos.
EASTL es una posibilidad, pero aún no es perfecto. Paul Pedriana de Electronic Arts realizó una investigación de varias implementaciones de STL con respecto al rendimiento en aplicaciones de juegos cuyo resumen se encuentra aquí: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007 /n2271.html
Algunos de estos ajustes están siendo revisados para su inclusión en el estándar C ++.
Y tenga en cuenta que incluso EASTL no optimiza para el caso no optimizado. Tuve un archivo Excel con algún tiempo hace un tiempo, pero creo que lo he perdido, pero para acceder fue algo así como:
debug release
STL 100 10
EASTL 10 3
array[i] 3 1
El mayor éxito que he tenido fue rodar mis propios contenedores. Usted puede obtener esos hasta casi el rendimiento de la matriz [x].
Echa un vistazo a EASTL .
Lo siento, no puedo dejar un comentario, así que aquí hay una respuesta: EASTL ahora está disponible en github: https://github.com/paulhodge/EASTL
Los contenedores STL no deberían ejecutarse "muy lentamente" en la depuración o en cualquier otro lugar. Quizás los estás mal usando. No se está ejecutando contra algo como ElectricFence o Valgrind en depuración ¿verdad? Reducen la velocidad de todo lo que hace muchas asignaciones.
Todos los contenedores pueden usar asignadores personalizados, que algunas personas usan para mejorar el rendimiento, pero nunca tuve que usarlos yo mismo.
MSVC usa una implementación muy pesada de iteradores marcados en compilaciones de depuración, que otros ya han discutido, por lo que no lo repetiré (pero comenzaré allí)
Otra cosa que podría interesarle es que su "compilación de depuración" y "compilación de versión" probablemente impliquen cambiar (al menos) 4 configuraciones que solo están relacionadas de manera vaga.
- Generando un archivo .pdb (cl / Zi y link / DEBUG), que permite la depuración simbólica. Es posible que desee agregar / OPT: ref a las opciones del enlazador; el vinculador elimina funciones sin referencia cuando no está haciendo un archivo .pdb, pero con el modo / DEBUG las mantiene todas (ya que los símbolos de depuración las referencian) a menos que lo agregue explícitamente.
- Utilizar una versión de depuración de la biblioteca de tiempo de ejecución de C (probablemente MSVCR * D.dll, pero depende del tiempo de ejecución que esté usando). Esto se reduce a / MT o / MTd (o algo más si no se usa el tiempo de ejecución dll)
- Desactivar las optimizaciones del compilador (/ Od)
- configurar el preprocesador # define DEBUG o NDEBUG
Estos se pueden cambiar de forma independiente. El primero no cuesta nada en el rendimiento del tiempo de ejecución, aunque agrega tamaño. El segundo hace que una serie de funciones sea más costosa, pero tiene un gran impacto en malloc y libre; las versiones de tiempo de ejecución de depuración tienen cuidado de "envenenar" la memoria que tocan con los valores para borrar los errores de datos no inicializados. Creo que con las implementaciones MSVCP * STL también elimina toda la agrupación de asignaciones que normalmente se realiza, de modo que las filtraciones muestran exactamente el bloque que se podría pensar y no un trozo de memoria más grande que ha estado subasignando; eso significa que hace que más llamadas a malloc sean mucho más lentas. El tercero; bueno, ese hace muchas cosas ( esta pregunta tiene una buena discusión sobre el tema). Desafortunadamente, es necesario si quieres que un solo paso funcione sin problemas. El cuarto afecta a muchas bibliotecas de varias maneras, pero lo más notable es que compila o elimina assert () y amigos.
Entonces, podría considerar hacer una compilación con una combinación menor de estas selecciones. Aprovecho mucho las compilaciones que usan símbolos (/ Zi y link / DEBUG) y afirma (/ DDEBUG), pero aún están optimizadas (/ O1 o / O2 o lo que sea que uses) pero con punteros de stack stack guardados para borrar trazas inversas (/ Oy-) y utilizar la biblioteca de tiempo de ejecución normal (/ MT). Esto se realiza cerca de mi compilación de lanzamiento y es semi-depurable (las trazas inversas son buenas, el paso simple es un poco raro en el nivel de la fuente, el nivel de ensamblaje funciona bien por supuesto). Puede tener todas las configuraciones que desee; simplemente clone su versión uno y active las partes de la depuración que parezcan útiles.
Mi experiencia es que el código STL bien diseñado se ejecuta lentamente en compilaciones de depuración porque el optimizador está desactivado. Los contenedores STL emiten una gran cantidad de llamadas a los constructores y operador = que (si son de poco peso) se ingresa / quita en las compilaciones de lanzamiento.
Además, Visual C ++ 2005 y versiones posteriores han habilitado la comprobación de STL en compilaciones de versión y depuración. Es un cerdo de gran rendimiento para el software pesado de STL. Se puede desactivar definiendo _SECURE_SCL = 0 para todas sus unidades de compilación. Tenga en cuenta que tener diferentes estados de _SECURE_SCL en diferentes unidades de compilación casi con toda seguridad provocará un desastre.
Puede crear una tercera configuración de compilación con la comprobación desactivada y usarla para depurar con el rendimiento. Sin embargo, te recomiendo que mantengas una configuración de depuración con verificación, ya que es muy útil detectar índices erróneos de matriz y cosas por el estilo.
Para aplicaciones grandes y de rendimiento crítico, construir sus propios contenedores específicamente adaptados a sus necesidades puede valer la pena el tiempo de inversión.
Estoy hablando sobre el desarrollo del juego real aquí.
Si está ejecutando estudios visuales, es posible que desee considerar lo siguiente:
#define _SECURE_SCL 0
#define _HAS_ITERATOR_DEBUGGING 0
Eso es solo para los iteradores, ¿qué tipo de operaciones de STL estás realizando? Es posible que desee considerar la optimización de sus operaciones de memoria; es decir, usar resize () para insertar varios elementos a la vez en lugar de usar pop / push para insertar elementos de a uno por vez.
Si está usando Visual C ++, debería echar un vistazo a esto:
http://channel9.msdn.com/shows/Going+Deep/STL-Iterator-Debugging-and-Secure-SCL/
y los enlaces de esa página, que cubren los diversos costos y opciones de todas las comprobaciones de modo de depuración que hace MS / Dinkware STL.
Si va a hacer una pregunta que depende de la plataforma, sería una buena idea mencionar su plataforma, también ...
Ultimate ++ tiene su propio conjunto de contenedores: no está seguro si puede usarlos por separado del resto de la biblioteca: http://www.ultimatepp.org/
Verificación de estructuras de datos y algoritmos con patrones de diseño orientados a objetos en C ++ Por Bruno Preiss http://www.brpreiss.com/
Qt ha vuelto a implementar la mayoría de las cosas de la biblioteca estándar de C ++ con diferentes interfaces. Se ve bastante bien, pero puede ser costoso para la versión con licencia comercial.
Editar: Qt fue lanzado desde LGPL , lo que generalmente hace posible su uso en productos comerciales sin la versión comercial (que también existe).