3.1 TIPOS DE OPTIMIZACIÓN Y 3.2 COSTOS.
3.1 TIPOS DE OPTIMIZACIÓN
Las optimizaciones pueden realizarse de diferentes formas. Las optimizaciones se realizan en base al alcance ofrecido por el compilador. La optimización va a depender del lenguaje de programación y es directamente proporcional al tiempo de compilación; es decir, entre más optimización mayor tiempo de compilación. La optimización es un proceso que tiene a minimizar o maximizar alguna variable de rendimiento, generalmente tiempo, espacio, procesador, etc.
3.1.1 Locales
La optimización local se realiza sobre módulos del programa. En la mayoría de las ocasiones a través de funciones, métodos, procedimientos, clases, etc. La característica de las optimizaciones locales es que solo se ven reflejados en dichas secciones. La optimización local sirve cuando un bloque de programa o sección es crítico por ejemplo: E/S, la concurrencia, la rapidez y confiabilidad de un conjunto de instrucciones. Como el espacio de soluciones es más pequeño la optimización local es más rápida. Como el espacio de soluciones es más pequeño la optimización local es más rápida.
• 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, y cuyas instrucciones se ejecutan secuencialmente. Implicaciones:
– Si se ejecuta una instrucción del bloque se ejecutan todas en un orden conocido en tiempo de compilación.
• 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.


Ensamblamiento (Folding)
• El ensamblamiento es remplazar las expresiones por su resultado cuando se pueden evaluar en tiempo de compilación (resultado constante).
– 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.
Implementación del Folding
• Implementación del floding 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.
– Se añade el procesamiento de las constantes a las reglas de análisis de expresiones.
– 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 del Folding
• 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.
3.1.2 Ciclos
Los ciclos son una de las partes más esenciales en el rendimiento de un programa dado que realizan acciones repetitivas, y si dichas acciones están mal realizadas, el problema se hace N veces más grandes. La mayoría de las optimizaciones sobre ciclos tratan de encontrar elementos que no deben repetirse en un ciclo.
Sea el ejemplo:
while(a == b) {
int c = a;
c = 5;
…; }
En este caso es mejor pasar el Int c =a; 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. Así que no todo código de proceso puede ser optimizado. Otros uso de la optimización pueden ser el mejoramiento de consultas en SQL o en aplicaciones remotas (sockets, E/S, etc.)
3.1.3 Globales
La optimización global se da con respecto a todo el código. Este tipo de optimización es más lenta pero mejora el desempeño general de todo programa. Las optimizaciones globales pueden depender de la arquitectura de la máquina. 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. Algunas optimizaciones incluyen utilizar como variables registros del CPU, utilizar instrucciones en ensamblador.
3.1.4 De mirilla
La optimización de mirilla trata de estructurar de manera eficiente el flujo del programa, sobre todo en instrucciones de bifurcación como son las decisiones, ciclos y saltos de rutinas. La idea es tener los saltos lo más cerca de las llamadas, siendo el salto lo más pequeño posible. Instrucciones de bifurcación Interrumpen el flujo normal de un programa, es decir que evitan que se ejecute alguna instrucción del programa y salta a otra parte del programa.
Por ejemplo: el “break”
Switch (expresión que estamos evaluando)
{
Case 1: cout << “Hola” ;
Break;
Case 2: cout << “amigos”;
Break;
3.2 COSTOS.
3.2.1 Costo de ejecución (Memoria, registros, pilas)
Los costos de ejecución son aquellos que vienen implícitos al ejecutar el programa. En algunos programas se tiene un mínimo para ejecutar el programa, 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.
Organización de la memoria en tiempo de ejecución
Las técnicas de gestión de la memoria durante la ejecución del programa difieren de unos lenguajes de programación a otros, e incluso de unos compiladores a otros.
Memoria
La memoria es uno de los recursos más importantes de la computadora y, en consecuencia, la parte del sistema operativo responsable de tratar con este recurso, el gestor de memoria, es un componente básico del mismo. El gestor de memoria del sistema operativo debe hacer de puente entre los requisitos de las aplicaciones y los mecanismos que proporciona el hardware de gestión de memoria.
Para que una variable pueda ser almacenada en memoria estática, es necesario conocer su tamaño (número de bytes necesarios para su almacenamiento) en tiempo de compilación. Como consecuencia, aunque una variable (u objeto) sea de ámbito global, no podrán ocupar almacenamiento estático: " Los objetos que correspondan a procedimientos o funciones recursivas, ya que en tiempo de compilación no se conoce el número de variables que serán necesarias. "

Registros
Los registros del procesador se emplean para controlar instrucciones en ejecución, manejar direccionamiento de memoria y proporcionar capacidad aritmética. Los registros son espacios físicos dentro del microprocesador con capacidad de 4 bits hasta 64 bits dependiendo del microprocesador que se emplee. Los registros son direccionables por medio de una viñeta, que es una dirección de memoria. Los bits, por conveniencia, se numeran de derecha a izquierda (15,14,13…. 3,2,1,0), los registros están divididos en seis grupos los cuales tienen un fin especifico.

Tipos De Registros
•Registros de Segmento
•Registros de Apuntador de Instrucciones
•Registros Apuntadores
•Registros de Propósito General
•Registros Índices
•Registros de Banderas
Pilas
Algunos lenguajes de programación utilizar la pila para almacenar datos que son locales a espacio para los datos locales se asigna a los temas de la pila cuando el procedimiento se introduce, y son borradas cuando el procedimiento termina.
3.2.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, 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. Los criterios de optimización siempre están definidos por el compilador. Muchos de estos criterios pueden modificarse con directivas del compilador desde el código o de manera externa. Este proceso lo realizan algunas herramientas del sistema como los ofuscadores para código móvil y código para dispositivos móviles.
3.2.3 Herramientas para el análisis del flujo de datos
Existen algunas herramientas que permiten el análisis de los flujos de datos, entre ellas tenemos los depuradores y desambladores. La optimización al igual que la programación es un arte y no se ha podido sistematizar del todo.
Depurador
Un depurador (en inglés: debugger) es un programa usado para probar y depurar (eliminar) los errores de otros programas (el programa "objetivo"). El código a ser examinado puede alternativamente estar corriendo en un simulador de conjunto de instrucciones (ISS), una técnica que permite gran potencia en su capacidad de detenerse cuando son encontradas condiciones específicas pero será típicamente algo más lento que ejecutando el código directamente en el apropiado (o el mismo) procesador. Algunos depuradores ofrecen dos modos de operación - la simulación parcial o completa, para limitar este impacto.
Deseamblador
Un desensamblador o disassembler es un programa de computador que traduce el lenguaje de máquina a lenguaje ensamblador, la operación inversa de la que hace el ensamblador. Un desensamblador difiere de un decompilador, en que éste tiene como objetivo un lenguaje de alto nivel en vez de al lenguaje ensamblador. la salida de un desensamblador, el desensamblado, es a menudo formateada para la legibilidad humana en vez de ser adecuada para la entrada a un ensamblador, haciendo que éste sea principalmente una herramienta de ingeniería inversa.
Comentarios
Publicar un comentario