<< Chapter < Page Chapter >> Page >

Una vez dividido el lenguaje intermedio en bloques básicos, hay diversas optimizaciones que pueden realizarse sobre el código de tales bloques. Algunas son muy simples y afectan a unas pocas tuplas dentro de un bloque básico. Otras mueven código de un bloque básico a otro, sin alterar los resultados del programa. Por ejemplo, a menudo resulta útil mover una cálculo desde el cuerpo de un ciclo al código que precede de forma inmediata al bucle.

En esta sección, vamos a listar por nombre las optimizaciones clásicas, e indicarle a usted para qué son. No estamos sugiriendo que usted haga los cambios; la mayoría de lso compiladores desde mitad de la década de 1980 realizan de modo completamente automático tales optimizaciones, excepto en el nivel más bajo de optimización. Como vimos a inicios del capítulo, si comprende usted aquello que pueden (y que no pueden) hacer los compiladores, se convertirá en un mejor programador porque será capaz de jugar con las fortalezas de ellos.

Propagación de copia

Para iniciar, veamos una técnica para desenredar cálculos. Échele un vistazo al siguiente segmento de código: observe los dos cálculos que involucran a X .


X = Y Z = 1.0 + X

Tal como está escrito, la segunda sentencia requiere del resultado de la primera antes de que pueda ejecutarse -requiere usted de X para calcular Z . Las dependencias innecesarias a menudo se traducen en retrasos a tiempo de ejecución. Este código es un ejemplo de dependencia de flujo. Describo las dependencias en detalle en [link] . Realizando algunos reacomodos, podemos hacer que la segunda sentencia sea independiente de la primera, al propagar una copia de Y . El nuevo cálculo para Z usa el valor de Y directamente:


X = Y Z = 1.0 + Y

Observe que dejamos intacta la sentencia X=Y . Puede que usted se pregunte, "¿por qué dejarla así?" El problema es que no podemos decir en qué otras partes se requiere el valor de X . Eso es algo que deberá decidir otro análisis. Si resulta que ninguna otra sentencia requiere del valor de X , la asignación se eliminará posteriormente, por medio de la remoción de código muerto.

Plegado de constantes

Un compilador inteligente puede encontrar constantes a lo largo de su programa. Algunas de ellas son “obvias”, como aquellas definidas en las sentencias de parámetros. Otras resultan menos obvias, tales como las variables locales que nunca se redefinen. Cuando las combina en un cálculo, obtiene una expresión constante . El pequeño programa siguiente tiene dos constantes, I y K :


PROGRAM MAIN INTEGER I,KPARAMETER (I = 100) K = 200J = I + K END

Dado que tanto I como K son constantes individualmente, la combinación de I+K es constante, lo cuál significa que J también es una constante. El compilador reduce las expresiones constantes como I+K a constantes, mediante una técnica llamada plegado de constantes .

¿Cómo funciona el plegado de constantes? Puede ver que es posible examinar cada camino en el cuál puede definirse una variable en ruta hacia un bloque básico particular. Si descubre usted que todos los caminos se inician en el mismo valor, éste es constante; puede reemplazar todas las referencias a esa variable con una constante. Este reemplazo tiene un efecto de rizado a lo largo de la ruta. Si el compilador se percata de que encontró una expresión compuesta solamente por constantes, puede evaluarla a tiempo de compilación y reemplazarla por una constante. Tras varias iteraciones, el compilador habrá localizado la mayoría de las expresiones que son candidatas al plegado de constantes.

Get Jobilize Job Search Mobile App in your pocket Now!

Get it on Google Play Download on the App Store Now




Source:  OpenStax, Cómputo de alto rendimiento. OpenStax CNX. Sep 02, 2011 Download for free at http://cnx.org/content/col11356/1.2
Google Play and the Google Play logo are trademarks of Google Inc.

Notification Switch

Would you like to follow the 'Cómputo de alto rendimiento' conversation and receive update notifications?

Ask