2012-05-29 18 views
16

He estado desarrollando código C++ para realidad aumentada en dispositivos ARM y la optimización del código es muy importante para mantener una buena velocidad de cuadros. Para elevar la eficiencia al nivel máximo, creo que es importante recopilar consejos generales que hagan la vida más fácil para los compiladores y reduzcan el número de ciclos del programa. Cualquier sugerencia es bienvenida.C++ Consejos para la optimización de código en dispositivos ARM

1- Evitar las instrucciones de alto costo: división, raíz cuadrada, seno, coseno

  • Use cambios lógicos para dividir o multiplicar por 2.
  • Multiplicar por la inversa cuando sea posible.

2- Optimizar interior "para" bucles: son un botleneck por lo que debemos evitar hacer muchos cálculos en el interior, especialmente divisiones, raíces cuadradas ..

3- Use tablas de consulta para algunas funciones matemáticas (sin, cos, ...)

herramientas útiles

  • objdump: obtiene el código de ensamblado del programa compilado. Esto permite comparar dos funciones y comprobar si está realmente optimizada.
+8

** Tenga cuidado **: hoy en día el cuello de botella es la memoria más de las veces (y por lo tanto LUT no son tan buenos ...). Puede ser diferente en ARM, hay que admitirlo, pero ... mejor que compruebes que inviertas para nada. –

+0

Sí. Pero en aplicaciones en tiempo real, realizando muchos cálculos por cuadro, créame que la optimización puede ahorrar "algunos fotogramas por segundo". Diga "algunos" son 8 cuadros por segundo, como en mi caso, por eso creo que esta pregunta es importante. –

+3

¿Tiene la posibilidad de verificar diferentes métricas, como errores de caché, accesos de bus de memoria, etc.? Esto también es muy útil para saber si su mem bus es un cuello de botella. Por cierto, fuera de tema, (donostia == San Sebastián)? Si es así, ¡realmente me gusta esa ciudad! – Brady

Respuesta

17

Para responder a su pregunta sobre normas generales para la optimización de código C++ para ARM, aquí hay algunas sugerencias:

1) Como usted ha mencionado , no hay instrucción dividida Use cambios lógicos o multiplique por el inverso cuando sea posible.
2) La memoria es mucho más lenta que la ejecución de la CPU; utilice operaciones lógicas para evitar tablas de búsqueda pequeñas.
3) Intente escribir 32 bits a la vez para hacer el mejor uso del buffer de escritura. Escribir cortos o caracteres ralentizará considerablemente el código. En otras palabras, es más rápido que lógico-O los bits más pequeños juntos y los escribe como DWORDS.
4) Tenga en cuenta su tamaño de caché L1/L2. Como regla general, los chips ARM tienen cachés mucho más pequeños que Intel.
5) Use SIMD (NEON) cuando sea posible.Las instrucciones NEON son bastante potentes y para el código "vectorizable", pueden ser bastante rápidas. Los intrínsecos de NEON están disponibles en la mayoría de los entornos C++ y pueden ser casi tan rápidos como escribir código ASM ajustado a mano.
6) Use la sugerencia de captación previa de caché (PLD) para acelerar las lecturas de bucle. ARM no tiene una lógica precache inteligente de la misma forma que los chips Intel modernos.
7) No confíe en el compilador para generar un buen código. Mire la salida de ASM y reescriba hotspots en ASM. Para la manipulación de bit/byte, el lenguaje C no puede especificar cosas tan eficientemente como se pueden lograr en ASM. ARM tiene poderosas instrucciones de 3 operandos, cambios múltiples de carga/almacenamiento y "libres" que pueden superar lo que el compilador es capaz de generar.

+0

Me gusta multiplicar por los cambios inversos y lógicos. También trato de usar punto fijo en dispositivos sin NEON. Actualizaré la publicación con tus sugerencias, ¡gracias! –

+0

Con respecto a 5): He visto bastantes discusiones SO sobre el uso de los intrínsecos de NEON. En resumen, parece que mucha gente está descubriendo que el compilador no está haciendo un buen trabajo traduciendo los intrínsecos en un buen código de ensamblaje. El consenso parece ser que si desea usar NEON, es mejor que lo escriba como código de ensamblaje directamente. – Leo

+0

@Leo - depende del compilador. GCC es muy malo compilando los intrínsecos de NEON. El LLVM de Apple es regular y los compiladores de Microsoft son bastante buenos. – BitBank

15

La mejor manera de optimizar una aplicación es utilizar un buen generador de perfiles. Siempre es una buena idea escribir código pensando en la eficiencia, pero también es mejor evitar hacer cambios donde "pienses" que el código puede ser lento, y esto podría empeorar las cosas si no estás 100% seguro.

Descubre dónde están los cuellos de botella y céntrate en ellos.

Para mí, el perfilado es un proceso iterativo, porque generalmente cuando se soluciona un cuello de botella, otros menos importantes se manifiestan.

Además de perfilar el SW, compruebe qué tipo de perfiles HW está disponible. Verifique si puede obtener diferentes métricas HW, como fallas en la memoria caché, accesos al bus de memoria, etc. Esto también es muy útil para saber si su bus mem o caché es un cuello de botella.

recientemente hice esta pregunta similar y tengo algunas buenas respuestas: Looking for a low impact c++ profiler

Cuestiones relacionadas