You are on page 1of 19

INSTITUTO TECNOLÓGICO SUPERIOR DE

COATZACOALCOS
TRABAJO DE LA TERCERA UNIDAD:

TITULO DE LA UNIDAD:
OPTIMIZACIÓN.
NOMBRE DEL ALUMNO:
GARCÍA ANTONIO OSWALDO.
NUMERO DE CONTROL:
11080870
CARRERA:
ING. EN SISTEMAS COMPUTACIONALES
MATERIA:
LENGUAJES Y AUTOMATAS ll
FECHA DE ENTREGA:
10/NOVIEMBRE/2014

1

.........................................2................... 18 3.............................................................. 13 3.....1.......................1 TIPOS DE OPTIMIZACIÓN ..................................................1.................................................1..........................................................2..............................2 CRITERIOS PARA MEJORAR EL CÓDIGO .....INDICE INTRUDUCCIÓN: ..........................1..................... 17 3.............................................................................................................................................................................................................................................................................................. 3 3...........................................2 COSTOS ........................ 4 3.................................................................................................................................................... 19 2 ..........................................................................................................................................................4 DE MIRILLA ....... 18 CONCLUSIONES .........................2...............2 CICLOS .........................3 HERRAMIENTAS PARA EL ANÁLISIS DEL FLUJO DE DATOS ................3 GLOBALES ........ 5 3............................... 10 3............ 17 3........... 18 3..1 LOCALES .................1 COSTOS DE EJECUCIÓN .........................

Objetivo:    Obtener código que se ejecuta más eficientemente según los criterios Tiempo de ejecución (optimización temporal) Espacio de memoria utilizado (optimización espacial) Funcionamiento   Revisa el código generado a varios niveles de abstracción y realiza las optimizaciones aplicables al nivel de abstracción Representaciones de código intermedio de más a menos abstractas 3 . de ciclos. globales y de mirilla. También veremos los tipos de optimización como lo son: locales. Sus costos en general y como mejorar el programa. de modo que resulte un código máquina más rápido de ejecutar.INTRUDUCCIÓN: En esta unidad veremos las técnicas y la fase de la optimización de código en si ambas son para mejorar el programa objeto para que este a su vez nos de un rendimiento mayor. La fase de optimización de código consiste en mejorar el código intermedio.

3. es decir. Desafortunadamente no existen optimizador que hagan un programa más rápido y que ocupe menor espacio. entre más optimización mayor tiempo de compilación. Algunos editores ofrecen una versión de depuración y otra de entrega o final. 4 . Las optimizaciones pueden realizarse de diferentes formas.1 TIPOS DE OPTIMIZACIÓN La optimización va a depender del lenguaje de programación y es directamente proporcional al tiempo de compilación. La optimización es un proceso que tiene a minimizar o maximizar alguna variable de rendimiento. se necesita de compiladores especiales para realmente optimizar el código. La mayoría de los compiladores tienen una optimización baja. es decir. espacio. Las optimizaciones se realizan en base al alcance ofrecido por el compilador de programación y es directamente proporcional al tiempo de compilación. La optimización se realiza reestructurando el código de tal forma que el nuevo código generado tenga mayores beneficios. generalmente tiempo. procesador. Como el tiempo de optimización es gran consumidor de tiempo (dado que tiene que recorrer todo el árbol de posibles soluciones para el proceso de optimización) la optimización se deja hasta la fase de prueba final. entre más optimización mayor tiempo de compilación. etc.

Las optimizaciones locales se realizan sobre el bloque básico • Optimizaciones locales – Folding –Propagación de constantes – Reducción de potencia – Reducción de subexpresiones comunes Bloque Básico • Un bloque básico es un fragmento de código que tiene una única entrada y salida. clases. Como el espacio de soluciones es más pequeño la optimización local es más rápida.1 LOCALES La optimización local se realiza sobre módulos del programa. métodos. • La idea del bloque básico es encontrar partes del programa cuyo análisis necesario para la optimización sea lo más simple posible. La optimización local sirve cuando un bloque de programa o sección es crítico por ejemplo: la E/S.1. Implicaciones: – Si se ejecuta una instrucción del bloque se ejecutan todas en un orden conocido en tiempo de compilación. – Ejemplo: A=2+3+A+C -> A=5+A+C • Estas optimizaciones permiten que el programador utilice cálculos entre constantes representados explícitamente sin introducir ineficiencias. procedimientos. etc. En la mayoría de las ocasiones a través de funciones. Ensamblamiento (Folding) • El ensamblamiento es remplazar las expresiones por su resultado cuando se pueden evaluar en tiempo de compilación (resultado constante). La característica de las optimizaciones locales es que sólo se ven reflejados en dichas secciones.3. y cuyas instrucciones se ejecutan secuencialmente. 5 . la rapidez y confiabilidad de un conjunto de instrucciones. la concurrencia.

– #define a 10 Con la ventaja que la variable puede ser local. Por ejemplo en C no hay constantes y será lo mismo utilizar – Int a=10. – Optimiza: 2+3+b -> 5+b • Hay una suma de constantes (2+3)+b – No optimiza: 2+b+3 -> 2+b+3 • No hay una suma de constantes (2+b)+3 Implementación posterior a la generación de código – Buscar partes del árbol donde se puede aplicar la propiedad conmutativa: • Sumas/restas: como la resta no es conmutativa se transforma en sumas: a+b-c+d -> a+b+(-c)+d • Productos/divisiones: como la división no es conmutativa se transforma en productos: a*b/c*e -> a*b*(1/c)*e – Buscar las constantes y operarlas – Reconstruir el árbol Propagación de constantes • Desde que se asigna a una variable un valor constante hasta la siguiente asignación. • Ejemplo: Propagación Ensamblamiento PI=3.14/180 -> G2R=0.14 -> PI=3. se considera a la variable equivalente a la constante. 6 .14 -> PI=3.14 G2R=PI/180 -> G2R=3.Implementación del Folding • Implementación del Folding durante la generación de código realizada conjuntamente con el análisis sintáctico – Se añade el atributo de constante temporal a los símbolos no terminales y a las variables de la tabla de símbolos. • Estas optimizaciones permiten que el programador utilice variables como constantes sin introducir ineficiencias. – Se añade el procesamiento de las constantes a las reglas de análisis de expresiones.017 PI y G2R se consideran constantes hasta la próxima asignación.

Ejemplo: – sustituir productos por sumas. Implementación de la Propagación de Constantes • Separar el árbol en bloques básicos – Cada bloque básico será una lista de expresiones y asignaciones • Para cada bloque básico – Inicializar el conjunto de definiciones a conjunto vacío.• Actualmente en C se puede definir const int a=10. a=2*a a=a+a – Evitar la operación append (++) A=length (s1 ++ s2) convertirlo en A=length (s1) + length (s2) 7 . – Para asignaciones • Eliminar del conjunto de definiciones la definición de la variable asignada • Añadir la definición de la variable asignada si se le asigna una constante Reducción de potencia (strength reduction) • Se busca sustituir operaciones costosas por otras más simples. • Definición: (variable.constante) – Procesar secuencialmente la lista de expresiones y asignaciones – Para expresión y asignación • Sustituir las apariciones de las variables que se encuentran en el conjunto de definiciones por sus constantes asociadas.

0 – Etc. después variables ordenadas alfabéticamente. • Las subexpresiones que aparecen más de una vez se calculan una sola vez y se reutiliza el resultado. Problema: Hay que trabajar con un grafo a cíclico. Para comparar dos expresiones se utiliza la forma normal • Se ordenan los operandos: Primero las constantes. Eliminación de subexpresiones redundantes. las variables indexadas y las Subexpresiones. Ejemplo X=C+3+A+5 -> X= 3+5+A+C Y=2+A+4+C -> Y=2+4+A+C • Divisiones y restas se ponen como sumas y productos para poder conmutar – A-B -> A+ (-B) – A/B -> A * (1/B) 8 . Estas sustituciones se representan como reglas que aplicará la reducción de potencia – Exp*1 -> Exp – 1*Exp -> Exp – Exp+0 -> Exp – 0+Exp -> Exp – Exp*cte(110) -> (Exp << 2)+(Exp << 1) – Exp*0 -> {llamar a las funciones de Exp } .Implementación de la Reducción de Potencia • Buscar subárboles que se puedan sustituir por otros menos costosos. • Dos expresiones pueden ser equivalentes y no escribirse de la misma forma A+B es equivalente a B+A. • Idea: Detectar las subexpresiones iguales y que las compartan diversas ramas del árbol.

• Hay que considerar las asignaciones que pueden convertir una subexpresion redundante en no redundante.Implementación • Primero se aplica el Folding y la propagación de constantes (“simplificar las expresiones”) • Después se reordena el árbol sintáctico hasta obtener la forma normal. • Recorrer el grafo a cíclico generado y sustituir la primera aparición de cada rama que sea hijo de dos o más nodos por una asignación a una variable local y las otras ramas por la variable local. Ejemplo: • Sustituir todas las variables asignadas por la expresión que se les ha asignado – Generar un orden de ejecución – Sustituir siguiendo este orden de ejecución • Comparar los subárboles desde las ramas hacia la raíz y sustituir los subárboles repetidos. 9 . • Se inicia la eliminación de las subexpresiones redundantes.

Ciclos while(a == b) { int c = a.) Optimizaciones Dentro de Bucles • La optimización de bucles es muy importante por las mejoras en tiempo de ejecución que se obtienen • Estrategias de optimización dentro de bucles – Expansión de bucles (loop unrolling) – Reducción de frecuencia (frequency reduction) – Reducción de potencia (strength reduction) 10 . E/S. •Otros uso de la optimización pueden ser el mejoramiento de consultas en SQL o en aplicaciones remotas (sockets.1. etc. •La mayoría de las optimizaciones sobre ciclos tratan de encontrar elementos que no deben repetirse en un ciclo. …. Así que no todo código de proceso puede ser optimizado. c = 5.3.2 CICLOS •Los ciclos son una de las partes más esenciales en el rendimiento de un programa dado que realizan acciones repetitivas. fuera del ciclo de ser posible. •El problema de la optimización en ciclos y en general radica es que muy difícil saber el uso exacto de algunas instrucciones. } En este caso es mejor pasar el int c =a. y si dichas acciones están mal realizadas. el problema se hace N veces más grandes.

• Ejemplo: – Invariantes: +. pero cada iteración del nuevo bucle corresponde a varias iteraciones del bucle original. Ejemplo: – Se puede aplicar a los bucles for i=1 to 10 do … – No se puede aplicar a los bucles for i=a to b do … • La expansión de un bucle puede ser muy costosa en espacio. • Las invariantes de bucle sólo pueden estar formadas por operaciones que son funciones puras – Su único efecto es el cálculo del resultado – El resultado solo depende de los operandos. sin. *. (frequency reduction) • La reducción de frecuencia detecta las operacionesinvariantes de bucle y las calcula una única vez delante del bucle. – Se puede aplicar una expansión parcial en la que sigue existiendo el bucle. getchar. Además el cálculo de la invariante puede producir un error de ejecución. – Esta transformación no tiene en cuenta que el bucle igual no se ejecuta ninguna vez y esto supondría perder tiempo de ejecución calculando la invariante de bucle innecesariamente. • En un bucle expandido se ha de sustituir el índice del bucle por el valor constante correspondiente. for i=1 to n do c=i*tmp. Por ejemplo una división por cero. – sin(a) es una operación invariante del bucle que puede pasar de calcularse n veces a una con la siguiente transformación tmp=sin(a). / . -. Reducción de frecuencia. ++. random 11 . ln – No invariantes: printf.Expansión de bucles (loop unrolling) • La expansión de bucles solo se puede aplicar a los bucles cuyo número de iteraciones se conoce en tiempo de compilación. Hay que poner un criterio heurístico para decidir si se aplica la expansión. Ejemplo: for i=1 to n do c=i*sin(a).

– Sustituir en el bucle las operaciones invariantes por las correspondientes variables. La solución es evaluar antes la condición de salida del bucle. – Marcar todas las operaciones no invariantes – Aplicar la siguiente regla recursiva para detectar las operaciones invariantes • Una operación es invariante si sus operandos son invariantes. comparaciones. • Problema del método anterior – Cuando no se entra en el bucle se calculan sus operaciones invariantes. Convertir en for (i=1. Ejemplo: operaciones aritméticas. – Añadir delante del bucle la asignación de la expresión invariante a su variable temporal. – Algunos compiladores permiten indicar que una función es pura para que pueda formar parte de invariantes. – Asociar a cada expresión invariante una variable temporal.++i) a[i]=3*i.++i. i<10. Implementación de la Reducción de Frecuencia • Pasos – Detectar todas las variables que se modifican en el bucle.i<10. Reducción de potencia (strength reduction) • Reducción de potencia aplicada a bucles – Sustituir productos entre variables inductivas e invariantes de bucle por sumas for (i=1.j+=3) a[i]=j.• Consideración práctica – Sólo pueden ser invariantes operaciones primitivas del lenguaje (son aquellas que implementa directamente el compilador). • Problemas a resolver – Detectar las invariantes de bucle • Ya está solucionado – Detectar las variables inductivas 12 . etc.j=3.

la eficiencia es una característica de estos métodos  Problemas de gran escala (+100 variables) son resueltos mejor con estos métodos estocásticosDeterminísticos: no envuelve ningún elemento aleatorio  Confiables:  Ramas y bordes (Branch and Bound). donde C es una invariante de bucle. búsqueda aleatoria (random search)  Sin embargo.3 GLOBALES La optimización global se da con respecto a todo el código.1. • Se considerará la necesidad de generar una variable inductiva temporal T a partir de encontrar expresiones de la forma V*C. donde K es una invariante de bucle. – Se sustituirá V*C por T – Se inicializa T después de la inicialización de V como T=V*C (solo se ejecuta al entrar en el bucle) – Al final de cada iteración se añade T=T+C*K 3. utilizar instrucciones en ensamblador.Variables Inductivas • Una variable V es inductiva cuando la única forma en que se modifica su código es V=V+K. Las optimizaciones globales pueden depender de la arquitectura de la máquina. métodos de intervalos (Interval methods)  Métodos de puntos (Point methods): calculan valores de la función sobre puntos de muestras (incapaces de resolver confiablemente un problema de optimización global). Algunas optimizaciones incluyen utilizar como variables registros del CPU. 13 . Tipos de optimización global  Estocásticos: evalúan f sobre una muestra aleatoria sobre la región de interés  No Confiables:  Simulado recocido (Simulated annealing). Este tipo de optimización es más lenta pero mejora el desempeño general de todo programa. En algunos casos es mejor mantener variables globales para agilizar los procesos (el proceso de declarar variables y eliminarlas toma su tiempo) pero consume más memoria. Ejemplo Monte Carlo.

Si son implementados apropiadamente y considerando errores de redondeo. Métodos de bordes (Boundary Methods): calculan cotas sobre conjuntos compactos. los vértices representan los bloques básicos y las aristas representan los saltos de un bloque básico a otro.  Ejemplo DIRECT. – El grafo de flujo de ejecución representa todos los caminos posibles de ejecución del programa. – Etc. – La información contenida en el grafo es útil para • El programador y el optimizador • La optimización global a partir del análisis del grafo del flujo de ejecución permite – Una propagación de constantes fuera del bloque básico. pueden producir soluciones globales rigurosas. 14 . • Un bloque básico será cualquier trozo de código que no contenga saltos ni etiquetas en su interior (es posible tener etiquetas al inicio del bloque y saltos al final). – En el grafo. – Eliminación del código no utilizado – Una mejor asignación de los registros. Optimización Global • Grafo del flujo de ejecución – Antes de realizar una optimización global es necesario crear el grafo de flujo de ejecución. • Problema: la optimización global es muy costosa en tiempo de compilación Construcción del Grafo del Flujo de Ejecución • Tipos de grafo – Orientado a procedimiento/función – Grafo de llamadas • Pasos – Dividir el programa en bloques básicos • Se representa el programa en un código intermedio donde queden explícitamente representados los saltos condicionales e incondicionales.

Expresiones Disponibles (Available expresions) • El problema de las expresiones disponibles consiste en determinar que expresiones están disponibles al inicio de cada bloque básico. • Una expresión está disponible en un punto si el resultado que se obtuvo cuando se calculó aún es el mismo que si se vuelve a calcular en el punto en que estamos. 15 . • Detección de código no utilizado – El código no utilizado son los bloques básicos donde no llega ninguna arista. – Se quita el bloque y las aristas que salen de él. • Esta información la representaremos en forma de conjuntos como los siguientes: – expresiones disponibles – Alcance de las definiciones – variables vivas – expresiones muy utilizadas Análisis del Grafo del Flujo de Ejecución • Los conjuntos se calculan para los puntos del grafo de flujo de ejecución.Detección de Código no Utilizado (Código Muerto) • Código muerto: es código que nunca se ejecutará. Análisis del Grafo del Flujo de Ejecución • Hay que considerar como la información sobre las variables y expresiones se propaga a través del grafo. • Un punto es una posición dentro del grafo y se encuentra entre instrucciones o bloques básicos. – Repetir hasta no eliminar ningún bloque básico. • Uso de las expresiones disponibles – Evitar recalcular la misma expresión (eliminación de subexpresiones redundantes) • Se ha calculado una expresión y tenemos guardado el resultado.

• Este valor definido se pierde cuando se realiza una nueva asignación.• Si más adelante hay que repetir el cálculo no será necesario hacerlo si es una expresión disponible. • Usos – delimitar exactamente en qué partes del código es necesaria una variable. Este se encuentra en un registro del procesador. – Eliminación de variables muertas y asignaciones innecesarias. Variables Vivas (live variables) • Una variable está viva en un punto p cuando su valor es requerido más adelante en un un camino de ejecución que pasa por p. Alcance de las Definiciones (reaching definitions) • El valor de una variable se define cuando se le asigna un valor. – Detectar el uso de variables no inicializadas • Se produce cuando intentamos leer el valor de una variable no definida. 16 . pero en el caso de las variables. – Propagación de constantes • Hay que ver que una variable está definida con una constante y se podrá sustituir por esta cuanto se quiera leer. • El problema del alcance de las definiciones es el mismo que el problema de las expresiones disponibles. • Si más adelante necesitamos el valor de la variable podemos evitar acceder a memoria y reutilizar el valor que hay en el registro si pertenece al conjunto de las definiciones. • Un camino requiere el valor de una variable cuando hay una lectura de la variable antes de una asignación. • Usos del alcance de las definiciones – Reutilización de copias en registros • Asignamos un valor a una variable.

Se utiliza una ventana de n instrucciones y un conjunto de patrones de transformación (patrón. Constituye una nueva fase aislada. la mejora obtenida puede ser N veces mayor por lo cual el costo se minimiza y es benéfico la mejora. si la ganancia es de 30 ms 300s 17 .) Si las instrucciones de la ventana encajan con algún patrón se reemplazan por lo secuencia de reemplazamiento asociada. La optimización de una pequeña mejora tal vez tenga una pequeña ganancia en tiempo o en espacio. 3. Aplicable en código intermedio o código objeto. Pero en cambio si esa optimización se hace por ejemplo en un ciclo. pero sale muy costosa en tiempo de generarla. ya que en ocasiones.1. i < 10000. secuencias reemplazan. •La idea es tener los saltos lo más cerca de las llamadas. siendo el salto lo más pequeño posible. la mejora obtenida puede verse no reflejada en el programa final. i++). pero sin ser perjudicial para el equipo de desarrollo. ciclos y saltos de rutinas. Las nuevas instrucciones son reconsideradas para las futuras optimizaciones.3. Idea Básica Se recorre el código buscando combinaciones de instrucciones que puedan ser reemplazadas por otras equivalentes más eficientes. sobre todo en instrucciones de bifurcación como son las decisiones. Por ejemplo: for(int i=0.2 COSTOS Los costos son el factor más importante a tomar en cuenta a la hora de optimizar.4 DE MIRILLA •La optimización de mirilla trata de estructurar de manera eficiente el flujo del programa.

Los criterios de optimización siempre están definidos por el compilador.2. la gran mayoría de las veces requieren de procesadores rápidos (e. el mejor uso de memoria y otros recursos de hardware tiene mayor rendimiento. La optimización al igual que la programación es un arte y no se ha podido sistematizar del todo. entre ellas tenemos los depuradores y desensambladores. por lo que el espacio y la velocidad de los microprocesadores son elementos que se deben optimizar para tener un mercado potencial más amplio. Los dispositivos móviles tiene recursos más limitados que un dispositivo de cómputo convencional razón por la cual.g.2.3 HERRAMIENTAS PARA EL ANÁLISIS DEL FLUJO DE DATOS Existen algunas herramientas que permiten el análisis de los flujos de datos.2 CRITERIOS PARA MEJORAR EL CÓDIGO La mejor manera de optimizar el código es hacer ver a los programadores que optimicen su código desde el inicio. En algunos programas se tiene un mínimo para ejecutar el programa. Las aplicaciones multimedia como los videojuegos tienen un costo de ejecución alto por lo cual la optimización de su desempeño es crítico.1 COSTOS DE EJECUCIÓN Los costos de ejecución son aquellos que vienen implícitos al ejecutar el programa.tarjetas de video) o de mucha memoria. el problema radica en que el costo podría ser muy grande ya que tendría que codificar más y/o hacer su código más legible. Muchos de estos criterios pueden modificarse con directivas del compilador desde el código o de manera externa. En algunos casos es preferible tener la lógica del negocio más fuerte en otros dispositivos y hacer uso de arquitecturas descentralizadas como cliente/servidor o P2P.3. 3. Otro tipo de aplicaciones que deben optimizarse son las aplicaciones para dispositivos móviles. 3. 18 .2. Este proceso lo realizan algunas herramientas del sistema como los ofuscadores para código móvil y código para dispositivos móviles.

todas tiene ventajas y desventajas.CONCLUSIONES En esta unidad vimos cómo se maneja la optimización para mejorar el código desde las bases locales hasta las globales sin dejar de lado claro el hecho de que hay ciclos de por medio. también se usan los criterios para mejorar el código como unos ya se encuentran definidos y más que nada hacer ver al programador que inicie la optimización de su código desde el inicio y por supuesto que use las herramientas que existen para analizar el flujo de los datos todo esto con un solo objetivo crear un mejor programa y código fuente. pero todo siempre va a la mejora y optimización del código. Tampoco podemos olvidar que para llevar acabo todo existen costos como lo son los costos de ejecución y que están muy ligados a lo que podrían ser los costos económicos. 19 .