Tema XII Optimización del código (Revision : 1,2) Herramientas de Programación. 13 de diciembre de 2005 Resumen Uso de las herramientas gprof y gcov en la optimización de código. Dpto. Lenguajes y Sistemas Informáticos Universidad de Alicante DLSI H.P.: Tema XII: Optimización del código - Revision : 1,2 Preliminares El objetivo de la optimización de código es cómo hacer que nuestros programas vayan más rápidos mediante la localización del los “cuellos de botella”. Para localizar esos cuellos de botella usaremos las herramientas: gprof: estudio de perfiles de ejecución. gcov: estudio de la cobertura de un test. DLSI 1 H.P.: Tema XII: Optimización del código - Revision : 1,2 ¿Para qué sirve gprof?: [I] La herramienta gprof nos proporciona perfiles de la ejecución de un programa, esto es, nos da información acerca de cuánto tiempo se emplea en cada función y de cuántas veces se llama. Sirve para detectar dónde el programa está invirtiendo la mayor parte de su tiempo de ejecución. DLSI 2 H.P.: Tema XII: Optimización del código - Revision : 1,2 ¿Para qué sirve gprof?: [II] Ejemplo 1 : Si tenemos un programa que gasta un 1 % de su tiempo en una cierta función, más vale descartar esta como objeto de optimización ya que no podremos mejorar significativamente la eficiencia del programa. Ejemplo 2 : Si tenemos una función que se llama muy a menudo desde una parte del programa y bajo unas condiciones muy concretas, estudiar el codificar una versión especializada de la misma. DLSI 3 H.P.: Tema XII: Optimización del código - Revision : 1,2 Tipos de perfiles Proporciona dos tipos de perfiles: Perfil plano : Para cada función proporciona el tiempo y el número de veces que se llama cada función. Grafo de llamadas : Lo mismo que la anterior pero con información acerca de qué funciones la llama y qué funciones llama. DLSI 4 H.P.: Tema XII: Optimización del código - Revision : 1,2 Ejemplo de perfil plano: [I] void h( int i) { ... } void f() { ... h(10); ... } void g() { ... h(1); ... } int main() { ... for(int i = 0; i < 10; i++ ) f(); ... for(int i = 0; i < 100; i++ ) g(); ... return 0; } DLSI 5 H.P.: Tema XII: Optimización del código - Revision : 1,2 Ejemplo de perfil plano: [II] Flat profile: Each sample counts as 0.01 seconds. % cumulative self self total time seconds seconds calls us/call us/call 48.79 5.03 5.03 110 45727.27 45727.27 48.79 10.06 5.03 100 50300.00 96027.27 2.42 10.31 0.25 10 25000.00 70727.27 DLSI name h(int) g(void) f(void) 6 H.P.: Tema XII: Optimización del código - Revision : 1,2 Ejemplo de grafo de llamadas: [I] index % time self children called name <spontaneous> [1] 100.0 0.00 10.31 main [1] 5.04 4.58 100/100 g(void) [2] 0.23 0.46 10/10 f(void) [4] ----------------------------------------------5.04 4.58 100/100 main [1] [2] 93.3 5.04 4.58 100 g(void) [2] 4.58 0.00 100/110 h(int) [3] ----------------------------------------------0.46 0.00 10/110 f(void) [4] 4.58 0.00 100/110 g(void) [2] [3] 48.9 5.04 0.00 110 h(int) [3] ----------------------------------------------0.23 0.46 10/10 main [1] [4] 6.7 0.23 0.46 10 f(void) [4] 0.46 0.00 10/110 h(int) [3] ----------------------------------------------DLSI 7 H.P.: Tema XII: Optimización del código - Revision : 1,2 ¿Cómo usar gprof? Compilar con la opción -pg y sin optimizar. Ejecutar el programa con un caso “tı́pico”, esto crea el fichero gmon.out. Ejecutar gprof nombre ejecutable Opciones: -p muestra el perfil plano de la ejecución. -q muestra el grafo de llamadas. -b no muestra la explicación de los perfiles. DLSI 8 H.P.: Tema XII: Optimización del código - Revision : 1,2 ¿Cuándo usar gprof? Cuando se tiene una versión estable de un programa y éste no es lo suficientemente rápido. A evitar: Optimizar versiones preliminares del programa Modificar la estructura (el diseño) del programa En estos casos se pierde flexibilidad y el programa será mas difı́cil de mantener. DLSI 9 H.P.: Tema XII: Optimización del código - Revision : 1,2 ¿Para qué sirve gcov? La herramienta gcov es un programa para hacer tests de cobertura. El programa devuelve una copia del programa fuente anotado con el número de veces que se ha usado cada lı́nea durante una o varias ejecuciones del mismo. Sirve para saber si hay partes del código que no han sido probadas durante la sesión de prueba y para saber qué partes se han usado más y son susceptibles de mejora. DLSI 10 H.P.: Tema XII: Optimización del código - Revision : 1,2 Ejemplo de fichero fuente anotado: [I] 1 1 10000 10000 ###### sum = 0; for( i = 0; i < count(vec); i++ ) if( vec[i] < 1.0 ) sum += vec[i]; else sum -= vec[i]; ¿Porqué la última lı́nea no se ejecuta nunca? test incompleto algo incorrecto DLSI 11 H.P.: Tema XII: Optimización del código - Revision : 1,2 Ejemplo de fichero fuente anotado: [II] 10001 10001 10001 int count( double vec[] ) { int cont; for( cont = 0; vec[cont] >= 0.0; cont++ ); return cont; } ¿Porqué se ejecuta 10001 veces? sacar la llamada a cont(double []) del bucle for. DLSI 12 H.P.: Tema XII: Optimización del código - Revision : 1,2 ¿Como usar gcov? Compilar sin optimizar con las opciones: -fprofile-arcs y -ftest-coverage. Crea ficheros con extensiones: .bb y .bbg que contiene información de la estructura del programa. Ejecutar el programa con un caso “tı́pico”. Crea un fichero con extensión .da que contiene información de contadores. Ejecutar gcov nombre fuente. Crea un fichero con extensión .gcov que contiene el fichero fuente anotado. Nota: si se ejecuta varias veces el programa, los contadores se suman. DLSI 13