I
¬
Educación Superior de Ensenada
g
'
'
i .
I
omuuzmlou Y rAuu.:uzAc|oN Au†oMA11cA
I E
nc |›noe|w4As Mmmm: ¡L noc|ssAM|:N†o
I
I
ne :Nro-mAc|oN nncomrua-rA
I
L
I
TESIS
MAESTRIA EN CIENCIAS
I
I
_J.REYESJUAREZ RAMIREZ
I
I
Y APRQBADA Pon EL s|Gu|EN†E corvnmå
/e%
Dr. Andrei Tchernykh
Director del Comité
ZC
g '
Dr. Gusïavo Iague Caballero ikhaìl Shlyagin
Miembro del Comité Miembro del Comité
¿ï/~/\/\/ I
Dra. Ewa Glowacka
Miembro del Comité
j/
í 1/ ,. ~ _/¡
M.C. José Luis Briseño Cervantes Dr. Federico Gr - le
Jefe de¡ Departamento de Director de Estudios de Posgrado
Ciencias de la Computación
CCIQESS
División de Física Aplicada
Departamento de Ciencias de la Computación
OPTIMIZACIÓN Y PARALELIZACIÓN AUTOMÁTICA DE
C PROGRAMAS MEDIANTE EL PROCESAMIENTO DE
INFORMACION INCOMPLETA.
TESIS
que para cubrir parcialmente los requisitos necesarios para Obtener el grado de MAESTRO EN CIENCIAS presenta:
J. REYES JUAREZ RAMÍREZ
OPTIMIZACION Y PARALELIZACION AUTOMATICA DE PROGRAMAS
MEDIANTE EL PROCESAMIENTO DE INFORMACION INCOMPLETA.
Resumen aprobado por:
Dr. Andrei Tchernykh Director del comité de Tesis
En este trabajo de tesis se estudia una nueva técnica de optimización automática de programas denominada evaluación parcial, basada en procesar información incompleta en una etapa previa a la ejecución final del programa. Las precomputaciones realizadas con esta técnica generan un código residual más simple de interpretar por parte del compilador y de una ejecución mas rápida con el resto de los datos de entrada.
Se estudia el modelo de computación paralela de la máquina de redes abstractas (ANM, por sus siglas en inglés) que aplica el procesamiento de información incompleta tanto en la evaluación, como en la ejecución del código. Este modelo se basa en la transformación de programas mediante redes asociativas, las cuales se reducen completa O parcialmente dependiendo de la disponibilidad de los datos de entrada, permitiendo de esta manera obtener un resultado final del programa 0 aplicar la evaluación parcial en forma
simple. '
` Se propone la aplicación de la evaluación parcial sobre la actividad de un intérprete para el lenguaje C en la ANM, como una nueva técnica de paralelizar programas imperativos en forma automática con un alto grado de eficiencia del paralelismo obtenido, en la cual no es necesario realizar un análisis sobre el código fuente para resolver problemas de la dependencia de datos, accesos concurrentes a memoria y efectos colaterales, como se hace en la paralelización tradicional.
AUTOMATIC OPTIMIZATION AND PARALLELIZATION OF PROGRAMS BY INCOMPLETE INFORMATION PROCESSING.
In this thesis work a new automatic Optimization technique named partial evaluation is studied. This technique is based on computation of incomplete information in a previous phase of final program execution. The result of precomputation is a residual code more easy to interpret by the Compiler and much faster to execute with the remainded data entry.
A model of parallel computation named Abstract Network Machine (ANM) is described which use incomplete information processing during program evaluation and execution. This model is based on program transformations using asociative networks. The networks are reduced fully or partialy in order of data entry availability, obtaining a program result or allowing to apply partial evaluation in traditional way.
A new technique for automatic parallelization of imperative programs is proposed. This technique applays partial evaluation to evaluate the activity of C program interpreter on ANM, achieving a high degree of efectiveness of the parallelism without performing a source code analysis to detect data dependences, memory concurrent accesses and side effects like in traditional parallelization.
A mis queridos padres, por la gran confianza y libertad que me han dado desde muy temprana edad para ir tras las metas que me he fijado.
A mis queridísimas hermanas, por todo su opoyo, la confianza y la fé que siempre han puesto en mí y por todas sus bendicionesi.
A mis queridos hermanos, en nombre del tiempo que no he compartido con ellos y de las metas que faltan por lograr juntos.
Al Consejo Nacional de Ciencia y Tecnología CONACYT, por su apreciable apoyo
brindado para la realización de mis estudios de maestría.
Al Centro de Investigación Científica y de Educación Superior de Ensenada CICESE, por darme la oportunidad de vivir la aventura de la investigación.
A los departamentos de Estudios de Posgrado y Ciencias de la Computación, por todas las facilidades brindadas para la realización de mis estudios.
Al Dr. Andrei Tchernykh por su acertada e inobjetable labor de dirección durante todo el desarrollo de mi trabajo de tesis. Gracias Dr. Andrei por su gran disponibilidad y
por toda su paciencial.
A los integrantes del comité de tesis, Dr. Gustavo Olague Caballero, Dr. Mikhail Shlyagin por su colaboración y en especial a la Dra. Ewa Glowacka por sus valiosas observaciones al documento de tesis.
A todos mis compañeros y a los investigadores de la maestría en Ciencias de la Computación por darme la oportunidad de crecer como ser humano.
Muy especialmente a mis compañeros Gilberto Ibarra y Yolanda Avila por todo su apoyo brindado durante el último año de mi estancia en CICESE y sobre todo al final de mi trabajo de tesis.
I
INTRODUCCION.
I. 1 Antecedentes.
1.2 Planteamiento del problema. I.3 Objetivo del trabajo de tesis.
I.4 Solución propuesta. 1.5 Alcances y limitaciones.
I.6 Estructura del trabajo de investigación.
II OPTIMIZACIÓN Y PARALELIZACIÓN DE PROGRAMAS.
Il.l Conceptos generales de la optimización de programas. II.2 Optimización automática realizada por el compilador. ll.2.1 Compiladores Optimizadores.
II.2.2 Optimizaciones logradas por los compiladores Optimizadores. H.3 Paralelización manual y automática.
H.3.1 Formas de paralelizar programas. II.4 Beneficios de la optimización.
II.5 Medición del desempeño de programas.
III
EVALUACION PARCIAL.
III.1 Especialización de programas. III.2 Principios de la evaluación parcial.
III.2.I Formulación semántica de la evaluación parcial. III.2.2 Utilidad y aplicaciones de la evaluación parcial.
III.3 Comparación de la evaluación parcial con la compilación tradicional. III.4 Tipos de evaluadores parciales.
III.4.l Análisis de tiempo de clasificación.
III.5 La especialización de programas en lenguajes imperativos.
III.5.1 La evaluación parcial en el lenguaje C.
III.5.2 Especialización del flujo de control. III.5.3 Especialización de funciones.
IV LA MÁQUINA DE REDES ABSTRACTAS.
IV.l Conceptos generales de los lenguajes declarativos. IV.2 Paralelismo soportado en la programación funcional.
IV.3 La máquina de redes abstractas. IV.3.1 Transformación de programas. IV.3.2 Conceptualizacion de la ANM.
IV.3.3 Representación de la información. IV.3.4 Conceptualización del programa.
IV.3.5 Proceso de cómputo.
IV.3.6 La evaluación parcial en la ANM.
IV.3.7 Paralelismo implícito en la codificación y ejecución del programa.
IV.-4 Métricas para la optimización en la ANM.
IV.5 El potencial de la ANM.
IV.5.l Uso de redes asociativas y operación única de redes. IV.5.2 Muitidireccionalidad de esquemas.
IV.5.3 Optimización en la implemtación de algoritmos.
IV.6 Comparación de la ANM y los evaluadores parciales tradicionales
V LA INCOMPLETITUD DE LA INFORMACIÓN.
V.l E1 procesamiento de información incompleta.
V.2 Incompletitud de la información en la evaluación parcial. V.3 Las estructuras incompletas (I-Structures).
V.4 Las estructuras dinámicas incompletas (DI-Structures) en la ANM V.5 Niveles de incompletitud de la información.
VI EXPERIMENTOS REALIZADOS.
VI.l Metodología para el desarrollo de experimentos.
V1.2 Multiplicación de matrices.
VI.2.1 Algoritmo para la multiplicación de matrices. VI.2.2 Análisis de la implementación.
VI.2.3 Optimizaciones realizadas en el lenguaje C. VI.2.4 Optimizaciones realizadas en lenguaje PARS. VI.2.5 Conclusiones.
VI.3 Aplicación del método iterativo de Jacobi.
VI.3.1 Descripción del algoritmo. Vl.3.2 Caso práctico
VI.3.3 Descripción de la implementación.
VI.3.4 Implementación en el paradigma imperativo. VI.3.5 Aplicación de la evaluación parcial.
VI.3.7 Conclusiones.
VII PARALELIZACION AUTOMATICA DE Mini-C.
VII.l Compilación por medio de la evalución parcial.
VII. l .1 Costo de la interpretación.
VII. 1.2 Optimalidad del evaluador parcial.
VII,1.3 Aplicación de la evaluación parcial en la ejecución del intérprete.
V1I.l .4 La paralelización lograda con la aplicación de la evaluación parcial VII.2 Sintaxis de C manejada en Mini-C.
VII.3 Semántica declarativa equivalente para Mini-C. VII.-4 Consideraciones de la implementación.
VII.5 Descripción de la paralelización lograda. VIl.6 Experimentos realizados.
VII.7 Conclusiones.
VIII CONCLUSIONES, APORTACIONES Y TRABAJO FUTURO
Vllll Conclusiones. VIII.2 Aportaciones. VIII.3 Trabajo futuro.
Apéndice A. Manual de referencia de PARS.
Apéndice B. Programas analizados y códigos especializados para los casos de prueba.
Vocabulario.
Figura 1. 2. 3. 4. ›-^›-›\OOO\lO\Ut I-*O 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28.
Estructura general del trabajo de investigación. Ejecución paralela de un programa.
Paralelización manual del código en C mediante el uso de un lenguaje
Power.
Paralelización automática del código en C mediante el uso de un analizador sintáctico.
Especialización de programas. Interpretación en un solo paso.
Compilación en dos pasos.
Especialización en tres pasos. Tipos de datos en la ANM.
Esquema MatrTR para la transposición de una matriz.
Objeto compuesto W con la matriz ml y el objeto desconocido para la matriz transpuesta.
Paso 1 del proceso de transposición de la matriz ml. Paso 2 del proceso de transposición de la matriz m1. Paso 3 del proceso de transposición dela matriz mI. Paso 4 del proceso de transposición de la matriz ml. Resultado de la transposición de mi .
Estructura del objeto X con dos atributos.
Consistencia de X después de la primera composición de v2. Consistencia final (temporal) del objeto X.
Clasificación de la incompletitud de la información.
Algortimo secuencial de la multiplicación de matrices. Implementación basada en el modelo SISD.
Código fuente para la especialización de la multiplicación de matrices. Desempeño del programa fuente de la multiplicación de matrices: compilación normal.
Desempeño del programa fuente de la multiplicación de matrices: compilación en el nivel O1.
Desempeño del programa fuente de la multiplicación de matrices: compilación en el nivel O2.
Desempeño del programa fuente de la multiplicación de matrices:
compilación en el nivel O3.
Desempeño del programa especializado de la multiplicación de matrices: compilación normal.
Aceleración para el programa de la multiplicación de matrices: programa especializado respecto al programa fuente.
Figura 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 4l. 42. 43. 44. 45. 46. 47. 48. 49. 50.
Aceleración para el programa de la multiplicación de matrices:
evaluación parcial y niveles de optimización respecto a la compilación
normal con el compilador gcc.
Aceleración para el programa de la multiplicación de matrices:
evaluación parcial y niveles de optimización respecto a la compilación
normal con el compilador cc.
Desempeño del programa de la multiplicación de matrices en el nivel Ol para los compiladores gcc y cc.
Desempeño del programa de la multiplicación de matrices en el nivel O2 para los compiladores gcc y cc.
Desempeño del programa de la multiplicación de matrices en el nivel O3 para los compiladores gcc y cc.
Comportamiento en el tamaño del código ejecutable especializado para
la multiplicación de matrices en los compiladores gcc y cc.
Multiplicación de matrices: implemetación l en lenguaje PARS. Multiplicación de matrices: implemetación 2 en lenguaje PARS. Multiplicación de matrices: implemetación 3 en lenguaje PARS. Desempeño del programa fuente para la multiplicación de matrices
en la ANM.
Desempeño del programa especializado para la multiplicación de
matrices en la ANM.
Aceleración para el programa de la multiplicación de matrices en ANM: programa especializado respecto al programa fuente. I
Comportamiento del tamaño del códi go especializado para la multiplicación de matrices en ANM.
Representación gráfica del suministro de calor a un material homogéneo. Representación matricial del problema del suministro de calor.
Implementación en C para el problema del suministro de calor.
Desempeño del programa fuente para el metodo de Jacobi en gcc y cc.
Desempeño del programa especializado para el metodo de Jacobi en
gcc y cc.
Aceleración con la evaluación parcial para el método de Jacobi en gcc y cc.
Desempeño del código especializado y los tres niveles de optimización para el método de Jacobi en gcc.
Desempeño del programa especializado y los tres niveles de optimización para el método de Jacobi en cc.
Desempeño de los programas fuente y especializado para el método de Jacobi compilados en en nivel O1.
Figura
51.
52.
53. 54. 55. 56. 57. 58.
Desempeño de los programas fuente y especializado para el método de Jacobi compilados en en nivel O2.
Desempeño de los programas fuente y especializado para el método de Jacobi compilados en en nivel O3.
Esquema principal (ciclo while) del método de Jacobi en PARS. Aceleración en la ejecución e incremento del tamaño para el programa del método de Jacobi en ANM.
Gramática de Mini-C en la forma Normal de Backus Nour (BNF). Registro de la actividad de un programa en memoria para un lenguaje
imperativo.
Registro de la actividad de un programa en memoria para un lenguaje declarativo.
Paralelización automática del código en C mediante la evaluación parcial.
Página
Tabla
I. Il.
Técnicas para la optimización de programas.
Ventajas y desventajas de las técnicas para la optimización de programas.
lll. Técnicas utilizadas en la paralelización de programas. IV. Ventajas y desventajas de las técnicas de paralelización.
V. Ventajas y desventajas de las técnicas de paralelización (continuación). VI. Formas de aplicar el procesamiento de información incompleta a nivel
de funciones.
VH. Aplicaciones de la evaluacion parcial. _
VIII. Aplicaciones de la evaluacion parcial (continuación). IX. Herramientas de software utilizadas en los casos de prueba. X. Características de la supercomputadora SGI Origin 2000. XI. Caracteríticas de la PC.
XII. Desempeño del programa fuente de la multiplicación de matrices con el compilador gcc.
XIII. Desempeño del programa fuente de la multiplicación de matrices con el compilador cc.
XIV. Desempeño del programa especializado de la multiplicación de matrices con el compilador gcc.
XV. Desempeño del código especializado de la multiplicación de matrices con el compilador cc.
XVI. Aceleración para el programa especializado y 1os niveles de
optimización en los compiladores gcc y cc. g XVII. Desempeño del programa fuente de la multiplicación de matrices en la
ANM.
XVIII. Desempeño del programa especializado de la multiplicación de matrices
en la ANM.
XIX. Radio de optimización para el programa de la multiplicación de matrices en la ANM.
XX. Desempeño del programa fuente para la aplicación del método de Jacobi con el compilador gcc.
XXI. Desempeño del programa fuente para la aplicación del método de Jacobi con el compilador cc.
XXII. Desempeño del programa especializado para la aplicación del método de Jacobi con el compiladorgcc.
XXIII. Desempeño del programa especializado para la aplicación del método de Jacobi con el compilador cc.
XXIV. Desempeño del programa fuente del método de Jacobi en ANM.
Tabla
XXV. Desempeño del programa especializado del método de J acobi en ANM. XXVI. Radio de optimización para el programa del método de J acobi en ANM. XXVII Desempeño de la interpretación del programa en C de la multiplicación
de matrices.
XXVIII Ventajas de la paralelización automática con el intérprete.
Página
Nomenclatura utilizada en las figuras:
Í
CJ
->
É
-›
:::::š>
Proceso
Datos, código fuente
Proceso cuya saiida es dato de entrada para otro proceso
Flujo de un actividad
Salida de un proceso
Secuencia de la aplicacion del procesamiento de información incompleta
I INTRODUCCIÓN.
I.1 Antecedentes.
Un programa es una serie de instrucciones escritas en algún lenguaje de
programación que la computadora ejecuta en un orden predefinido por la sintaxis del
lenguaje. Generalmente las instrucciones son una combinación de operandos y operadores,
donde los operadores representan operaciones o tareas específicas y los operandos son
datos sobre los cuales se realizan esas Operaciones. En la ejecución de un programa cada
instrucción es realizada Siempre y cuando existan todos los operandos involucrados. Si un
dato relacionado en una instrucción no se encuentra disponible al momento de la
evaluación, esa instrucción no se realiza y por lo tanto se puede alterar el flujo de la
computación, provocando que el programa no sea ejecutado en su totalidad y que no se
obtenga un resultado final.
Asegurando una totalidad de los datos de entrada, un programa puede ser
optimizado en cuanto al tiempo de ejecución mediante técnicas tradicionales tales como:
distintas implementaciones de un programa (usando distintos algoritmos para la solución
del problema) realizadas por el programador, empleo de los potenciales del lenguaje de
De la misma manera, la completitud de los datos de entrada y del código permiten la
paralelización de programas, donde varios procesadores ejecutan el código logrando
menores tiempos de ejecución que en la forma secuencial (un solo procesador).
Existen en la actualidad compiladores Optimizadores y paralelizadores para los
lenguajes imperativos secuenciales, pero en muchas ocasiones la optimización y la
paralelización automática no generan resultados lo suficientemente satisfactorios,
obligando al programador a realizar manualmente la actividad de mejoramiento del código.
Tanto las Optimizaciones logradas por el programador, como la paralelización manual
requieren la inversión de cierta cantidad de tiempo y esfuerzo para su implementación, por
tal motivo, la aplicación de nuevas técnicas y el desarrollo de herramientas que realicen la
actividad de optimización, se convierten en un tema de vital importancia en la evolución de
la ciencia de la computación.
I.2 Planteamiento del problema.
La rapidez de ejecución de un programa depende de varios factores tales como: la
complejidad de interpretación de las instrucciones, la disposición de datos/código en
memoria y de la cantidad de cálculos requeridos para obtener el resultado final. El proceso
de ejecución de un programa escrito en un lenguaje fuente normalmente Se divide en dos
pasos: la compilación y la ejecución. En ambas etapas se pueden realizar acciones para
mejorar la ejecución del código y como consecuencia el tiempo de ejecución. Los esfuerzos
en la compilación deben estar orientados a realizar el máximo número de operaciones
aplicables en la compilación son: la ejecución integral de un programa, la computación
compuesta y la especialización de datos (Knoblok y Ruf, 1996). En la ejecución integral de
un programa se realiza una ejecución parcial del código, generando resultados intermedios
almacenados en un caché, de donde serán extraidos los valores en llamadas subsecuentes
del mismo código. La computación compuesta realiza una evaluación del código y de los
datos simultáneamente, dejando un código más simple y manipulable que permite agilizar
el proceso de ejecución. La especialización de datos centra su actividad en fragmentos de
código respecto a ciertos datos constantes, manejando una salida en un caché especial, el
cual puede ser accesado cuando se requiera extraer valores de las precomputaciones
realizadas. Esta técnica realiza una transformación de código de fuente a fuente, dando la
posibilidad de integrar este código con el resto del programa en la evaluación final. Otra
técnica más popular desde el punto de vista del programador es la actividad propia del
compilador. Las estrategias de precomputación y las Optimizaciones del código que realiza
el compilador se hacen en tres niveles distintos, permitiendo optimizar la ejecución de un
programa en gran medida, pero con la limitante de que funcionan sólo para ciertas
arquitecturas O ambientes de computación.
En la paralelización del código es posible utilizar varias técnicas enfocadas a
realizar esfuerzos previos a la ejecución: la calendarización de trayectorias, la calendarización estática y la paralelización implementada por el “Supercomputer toolkit” (Surati y Berlin, 1994). En la calendarización de trayectorias se realiza la compilación
explotando el paralelismo de granularidad fina, logrando la ejecución simultánea de
grado de análisis para definir el flujo de la computación (ejecución de ramificaciones
condicionales) y una fase de ajuste de la granularidad a las características del hardware
utilizado para ejecución. La calendarización estática trabaja con el paralelismo de
granularidad fina contenido en grandes segmentos de código. Esta técnica requiere de un
análisis minucioso para detectar el paralelismo y de mucho control para la administración del mismo. La paralelización lograda por el “Supercomputer toolkit” es una combinación la
evaluación parcial del código (precomputaciones) y de la calendarización estática. En este
método, primero se reduce la complejidad del código realizando precomputaciones en base
a la disposición de información constante, para después administrar el paralelismo existente
mediante la calendarización estática. El grado de ejecución paralela que se obtiene depende
del esfuerzo realizado en la adecuación de la granularidad de la computación con la
arquitectura del hardware.
Otras formas más comunes de realizar la paralelización de programas son la
paralelización manual o también conocida como reestructuración iterativa (Surati y Berlin,
1994) y la paralelización automática realizada por un analizador de código. La forma
manual se basa en la paralelización explícita realizada por el programador, quien debe de
reestructurar el programa cuantas veces sea necesario hasta lograr el grado de
paralelización requerido, apoyándose en la sintaxis de un lenguaje de programación
paralelo (SGI Doc. Num. 007-0702-050) o en el mejoramiento de la implementación del
algoritmo. El método automático de paralelización, aunque libera al programador de la
trabaja solamente sobre algunas estructuras cíclicas de la sintaxis del lenguaje de
programación paralelo (SGI Doc. Num. 007-0702-050).
Tanto las técnicas de optimización, como las técnicas de paralelización descritas,
presentan cierto nivel de complejidad en cuanto a su implementación y para la
manipulación por parte del programador al momento de desarrollar un programa para la
solución de un problema. En base a esto, es conveniente estudiar otras alternativas que
permitan lograr niveles aceptables de optimización y que requieran un menor esfuerzo para
su implementación.
I.3 Objetivo del trabajo de tesis.
Estudiar la aplicabilidad del procesamiento de información incompleta en la
optimización y paralelización de programas considerando los paradigmas de programación
imperativo y declarativo. Específicamente se analizan las técnicas de evaluación parcial y
la transformación de programas mediante redes asociativas, las cuales manejan distintos
niveles de incompletitud de la información.
1.4 Solución propuesta.
En este trabajo de tesis se estudia otra alternativa para realizar precomputaciones
antes de la compilación, denominada evaluación parcial. Esta técnica difiere de las
mencionadas anteriormente en que es más simple de aplicar, ya que trabaja sobre la
ejecución de instrucciones de código fuente sólo en base a la información disponible al
fácil de integrar con el resto del programa y de gran accesibilidad por parte del compilador,
ya que el código original es transformado en un código escrito en el mismo lenguaje del
programa fuente. Este nivel de transformación logrado brinda la oportunidad de que la
compilación se ejecute en forma normal.
Para eficientar la computación en la fase de ejecución (tiempo de corrida), se utiliza
una técnica de transformación de programas usando redes asociativas, mediante las cuales
se representan tanto el código, como los datos. La evaluación de las redes se realiza sin
seguir un orden estricto de consecutividad y en forma paralela, lo cual permite procesar
parcialmente secciones de código que serán completadas mediante instancias con valores
específicos resultantes de otras redes evaluadas. El control de la granularidad obtenida no
requiere de un alto grado de esfuerzo y no es necesaria una calendarización de la actividad
paralela. El paralelismo es inherente a la estructura de las redes, las cuales permiten una
granularidad a nivel de nodos. Para que un programa se ejecute y genere un resultado final
se requiere de la disposición de toda la información a procesar, sin embargo, bajo este
enfoque de redes asociativas, también se pueden realizar precomputaciones sobre un
programa cuando los datos de entrada no están completos, logrando el efecto de la
evaluación parcial aplicada antes de la compilación. I
Bajo este panorama, se propone una combinación de la evaluación parcial bajo el
sistema de redes asociativas y la actividad de un intérprete para lograr el efecto de
compilación. Aquí las precomputaciones se realizan sobre el programa que es interpretado
en base a la disponibilidad de sus datos de entrada. De esta manera, el trabajo de cómputo
transformaciones tales como el cambio de estilo de iterativo a recursivo, la migración del
paradigma de programación de imperativo a declarativo y un cambio del modelo de
ejecución de secuencial a paralelo. Con estas tranformaciones alcanzadas, se logra superar
la simple transformación de código fuente a fuente y la creación de objetos (caché, tablas
de valores, etc.) contenedores de las precomputaciones con un complicado método de
EICCCSO.
I.5 Alcances y limitaciones.
Debido a que la incompletitud de la información en un programa puede presentarse
en diferentes niveles y a que los paradigmas de programación tiene propiedades distintas,
en primera instancia se hace un estudio por separado de las posibilidades de realizar
procesamientos parciales en cada uno de ellos, aplicando técnicas únicas o una
combinación de las mismas. En el caso del paradigma imperativo se utiliza la evaluación
parcial mediante el uso de una herramienta automática o evaluador parcial, que realiza
transformaciones simples del código, las cuales reducen el trabajo de interpretación por
parte del compilador. El evaluador parcial realiza una transformación de código de fuente a
fuente, lo que permite la portabilidad del código especializado a diferentes plataformas de
hardware y la utilización de diferentes compiladores para generar el código ejecutable. Con
esto, es posible mostrar la operatividad de la evaluación parcial aplicada a los lenguajes
imperativos. En el caso del paradigma declarativo se utiliza una combinación de la
evaluación parcial y del enfoque transformacional en la representación de programas,
incompleta tanto en la evaluación, como en la ejecución de un programa en forma paralela.
Este modelo de computación no permite la portabilidad del código especializado debido a
que se trabaja en un ambiente propietario, esto es, el sistema tiene su propio lenguaje de
programación, su propio compilador y el código ejecutable es único para esta máquina de
ejecución. Sin embargo, las propiedades del lenguaje de programación utilizado y la
emulación del ambiente de computación paralela que maneja este modelo permiten un alto
grado de fidedignidad de los resultados obtenidos, de tal manera que es fácil mostrar la
operatividad del procesamiento de información incompleta bajo este enfoque, tanto en la
optimización, como en la paralelización de programas.
Cabe mencionar que el grado de paralelización que se logra sobre el código
secuencial imperativo, representa una innovación en el campo de la computación paralela,
puesto que hasta la fecha poco se sabe a cerca de este tipo de tranformaciones realizadas
sobre programas. El intérprete se desarrolla bajo el paradigma declarativo y sirve para
traducir el código secuencial de C a un código declarativo paralelo en lenguaje PARS.
I.6 Estructura del trabajo de investigación.
En la figura 1 se muestra el marco general del trabajo de investigación, indicando
las distintas posibilidades de optimizar 'y paralelizar un programa. Las flechas sencillas en
la parte izquierda del diagrama indican los caminos a seguir para mejorar la ejecución de
un programa. Con flechas dobles y punteadas se indican dos alternativas de aplicar el procesamiento de información incompleta mediante la evaluación parcial y la
posibilidades de realizar transformaciones sobre los programas imperativos, mediante el
uso de la evaluación parcial directamente sobre el programa fuente o a través de su
aplicación sobre la actividad del intérprete.
Código ejecutable secuencial imperativo Código ejecutable
secuencial imperativo P' k U Ñ
cornpileicion [optimizeiciori]
L J
Y' _ _ _, Ñ
Optimizacion manual, automática
L J _
Eveiliiador çúmgü ESPECIE' imperativo Parcial mati? 8E'3u'.3"C"aI
imperativo
` ' II
imperativo H
SBCUEÑCIÚI Parcial Poiolelizoicion
`\
\\
imperativo declarativo "ï*`\
\"` `
imperativo \
r'
' P ieiizfieien `
, ' - ec
-~
A
mii@
---~-ANM ---H.,§,r.°,,ss.,.¿fl
declarativodatos de entrada EjE¢._¡¢¡¿m
completos paralela '
Código ejecutable
Í Ñ
K para C Á
paralelo imperativo
Figura l. Estructura general del trabajo de investi gación.
Tomando en consideración los conceptos involucrados para lograr el Objetivo
secuencia que a continuación se indica. En el capítulo II exponen los conceptos generales
de la optimización de programas, precisando los parámetros de medición utilizados para
evaluar el nivel de mejoramiento logrado en la ejecución del código. En el capítulo HI se
hace una descripción completa de los conceptos de la evaluación parcial con el fin de
justificar su aplicabilidad en el mejoramiento del desempeño de un programa. En el
capítulo IV se describe la máquina de redes abstractas (ANM, por sus siglas en inglés) de
una manera detallada, no solamente para validar su aplicabilidad, sino también como una aportación de este trabajo de tesis. En el capítulo V se precisan los diferentes niveles de
incompletitud de la información manejados en la evaluación parcial y en el modelo de
computación de la ANM. El capítulo VI presenta los experimentos realizados y los
resultados obtenidos utilizando las dos técnicas propuestas. En "el capítulo VII se describe
la implementación de la paralelización automática del código en C y los resultados de los
experimentos realizados. En el capítulo VIH se presentan las conclusiones generales de la
investigación, las aportaciones realizadas y se plantea el trabajo futuro para dar
continuación al tema de estudio.
Este documento se completa con dos apéndices y un vocabulario que contiene los
términos importantes que son manejados en el documento, pero que no forman parte del
trabajo de investigación. El apéndice A contiene los conceptos generales de la sintaxis del
lenguaje PARS. El apéndice B contiene los programas con las anotaciones realizadas en la
II LA OPTIMIZACIÓN Y PARALELIZACIÓN DE PROGRAMAS.
La actividad de cómputo es realizada mediante una combinación de distintos
elementos del sistema tales como: uso del procesador (CPU, por sus siglas en inglés),
memoria principal y canales de comunicación. Para realizar una operación, el procesador
emplea varios ciclos de reloj y se mantiene ocupado cierta cantidad de tiempo según la
naturaleza de esa operación. Cuanto más compleja es una operación, más grande será el
tiempo de ejecución. La memoria sirve para alojar los datos de entrada al programa, lo
mismo que los datos generados durante el procesamiento. La colocación (ubicación física)
y la disposición (existencia temporal) de los datos en la memoria son factores que
determinan la rapidez de acceso, que finalmente se traduce en tiempo de trabajo del
procesador y por consiguiente, en tiempo de ejecución. Reducir la complejidad de una
operación y mejorar la disposición de los datos son los elementos más importantes para
reducir el tiempo de ejecución de un programa.
Este capítulo está estructurado de la siguiente manera: la sección II.1 trata varias de
las técnicas aplicables en la optimización y paralelización, enfocadas a la forma automática
de aplicación; las sección II.2 y II.3 describen la forma automática de realizar la
optimización y la paralelización por parte de los compiladores y los analizadores de
código; la sección II.4 resume brevemente los beneficios obtenidos con la optimización de
programas; y la sección [L5 describe las forma de medir el rendimiento obtenido con las
II.1 Conceptos generales de la optimización de programas.
La optimización de programas “es la búsqueda de la versión ejecutable del código
que usa el mínimo de recursos críticos de una plataforma de hardware, incluyendo ciclos
del procesador, memoria primaria y dispositivos de entradajsalida”.
Dos formas simples de realizar la optimización de un programa son la realizada por
el programador y la que realiza el compilador. El programador se concentra principalmente
en la modificación del código fuente después de la primera implementación (por ejemplo:
usando funciones de librería en lugar de funciones propias), lo mismo que en resolver un
problema mediante diferentes algoritmos o escribiendo un programa para cada
implementación. En caso de que se utilice el compilador como una fuente directa de
optimización, el programa que se desea mejorar puede ser evaluado en diferentes
compiladores, puesto que cada uno puede tratar en forma distinta los tipos de datos y el
manejo de memoria (factores que pueden determinar la rapidez de ejecución del código
resultante), obteniendo de esta manera tiempos distintos de ejecución. Por otro lado, el
compilador proporciona tres niveles de optimización adicionales a la compilación normal.
Con estos niveles de optimización se realizan optimizaciones en diferentes proporciones
sobre un mismo código fuente; explotando aspectos de la sintaxis del lenguaje o algunos
mecanismos específicos del manejo de tipos de datos y la representación de números.
En las tablas I' y II se hace un resumen de algunas de las técnicas existentes para la
optimización de programas, algunas de las cuales son poco manejadas por el programador,
ya que están basadas en la realización automática del proceso de optimización. La forma de
Toda esta labor de optimización es efectuada en el ámbito de la computación
secuencial, principalmente para el paradigma imperativo y en menor proporción para el
declarativo.
Tabla I. Técnicas para la optimización de programas.
Técnicas Descripción Referencias
Optimización del compilador
Realiza precomputaciones sobre datos conocidos y transformaciones
sintácticas.
Salida: código objeto.
(SGI Doc. Num. 8057)
Generación de
código en tiempo de
corrida
Especialización de código constante almacenada en tablas de consulta para el instanciamiento de valores en el código generado dinámicamente. Salida: tablas de consulta.
(Knoblok y Ruf, 1996),
(Consel y Noël, 1999)
Ejecución
incremental de un programa
Ejecución parcial del código generando
resultados intermedios en un caché par llamadas subsecuentes.
Salida: caché de código especializado.
2:1
(Knoblok y Ruf, 1996), (Hoover, 1992)
Evaluación parcial Ejecución parcial de instrucciones en base a la disposición de los datos. Transformación de código de fuente a fuente.
Salida: código fuente
(Knoblok y Ruf, 1996),
(Jones et al., 1993),
(Jones, l996a)
Especialización de
datos
Especialización de fragmentos de código respecto a ciertos datos con salida a un caché especial.
Transformación de código de fuente a fuente.
Salida: caché de datos especializados.
(Knoblok y Ruf, 1996)
En la computación paralela, que es otra forma de optimizar la ejecución de un
programa, la actividad del programador se concentra básicamente en la paralelización
explícita del código secuencial para el caso de un lenguaje imperativo. De la misma manera
paralelización, enfocándose a estructuras de control simple como es el caso de los ciclos,
en la programación multihilos o en técnicas específicas de pase de mensajes. Cuando se
trabaja con un lenguaje declarativo, el programador trabaja mas bien en la implementación
adecuada del algoritmo puesto que este tipo de lenguajes poseen un paralelismo implícito,
como es el caso de los lenguajes funcionales.
Tabla H. Ventajas y desventajas de las técnicas para la optimización de programas.
Técnicas Ventaj as Desventajas
Optimización del compilador
-Ejecución automática de la optimización.
- Aplicabilidad en programas
completos.
- Rapidez de ejecución por la adecuación del código de la máquina. .
Código optimizado para
arquitecturas particulares.
Generación de código en tiempo
de corrida
- Altos niveles de aceleración] debido a la completitud del código precompilado. - Portabilidad en el uso de bloques de código
especializado (adecuación con el código fuente).
Se requiere de muchas instrucciones dinámicas para generar una instrucción optimizada.
Ejecución
incremental de un programa
- Reusabilidad del código. - Revisión dinámica de las dependencias.
-Más trabajo durante la compilación.
- Reconstrucciones dinámicas por cada cambio de las entradas al programa.
Evaluación parcial - Uso general debido a su
aplicación sobre aspectos básicos del código.
- Sencillez del código residual
- Grandes códigos residuales.
- Aplicabilidad sobre módulos o funciones.
Especialización de
datos
Un costo adicional 2 bajo en tiempo y espacio.
Es aplicable sólo a fragmentos de programas
aceleración' (speedup). Es una mcdida que define el beneficio relativo de ejecutar un programa (código) cn
forma optimizada o cn forma paralela.
En las tablas III, IV y V se presenta una relación de las técnicas existentes en la
paralelización de programas (Surati y Berlin, 1994), la mayoría de las cuales funcionan en
forma automática. La descripción precisa las ventajas y desventajas que tiene cada una de
las técnicas, esto con el fin de hacer una comparación con la paralelización lograda
mediante la propuesta que se hace en este trabajo de tesis.
Tabla III. Técnicas utilizadas en la paralelización de programas.
Técnica Descripción
Calendarización de trayectoria
Compilación explotando el paralelismo de granularidad fina mediante técnicas de
calendarización de trayectoria para permitir el paralelismo de ramificaciones e instrucciones
precedentes.
Supercomputer Toolkit
Ajustar el tamaño de la granularidad de la computación a la arquitectura de hardware tanto como sea posible, apoyándose en la evaluación parcial y usando la calendarización
estática.
Software pipeline Paralelización basada en la repartición de iteraciones entre diferentes procesadores en intervalos constantes de tiempo.
Vectorización Ejecución paralela de las operaciones de cada elemento del vector.
Reestructuración Iterativa
Enfoque manual de paralelización, hasta lograr un reconocimiento automático del paralelismo existente.
Cal endarización
estática
Calendarización estática de paralelismo de granularidad fina contenida en bloques de código.
La técnica de evaluación parcial se describe ampliamente en el capítulo III pero se
consideró conveniente relacionarla con las técnicas de optimización y paralelización
complejidad que presenta. Haciendo un análisis de su operatividad comparada con las
técnicas mostradas en tabla IV, se hace notar una de sus principales desventajas, la cual se
expresa en términos de la eliminación de todo el paralelismo de granularidad fina expuesto
en la evaluación del código fuente (ciclos) que está disponible para la computación
paralela. Los efectos de esta desventaja se reflejan sobre todo si la evaluación parcial se
aplica antes de la compilación, combinada con la paralelización automática realizada por
un analizador que no emplea una estrategia eficiente para la administración del
paralelismo.
Tabla IV. Ventajas y desventajas de las técnicas de paralelización.
Técnica Ventajas Desventajas
Calendarización de Permite paralelizar las -Se requiere de una fase de trayectorias estructuras condicionales junto ajuste de la granularidad con
1 con actividades precedentes. las características del hardware.
- Formación de bloques i pequenos de instrucciones (10
instruciones).
Supercomputer -Genera bloques de código Es dependiente de la Toolkit grandes empleando la evaluación arquitectura en la cual
parcial en la eliminación de funciona el compilador. ramificaciones condicionales.
-Elimina la necesidad de escribir programas en un estilo de
paralelismo explícito.
Software pipeline Optimiza la ejecución de ciclos - La efectividad depende de la (loops) con la ejecución granularidad del paralelismo multiprocesador en intervalos expresada en la codificación
constantes de tiempo. para su adecuación con el hardware.
Tabla V. Ventajas y desventajas de las técnicas de paralelización (continuación).
Técnica Ventaj as Desventajas
Vectorización -Altamente efectiva asegurando
una computación compuesta por operaciones del vector legibles e identificables.
- Útil en computaciones con alto grado de dependencia de datos o con un alto grado de estructuras
irregulares que limitan el
desplegado de ciclos.
-Bajo desempeño cuando se requiere acceso a la estructura
del ciclo contenida en el
vector. '
- Falla debido a que la estructura de la computación no se presta en sí misma a la representación orientada al
vector.
Reestructuración iterativa
Se tienen control sobre el grado de paralelización requerido.
Escritura y reescritura manual del código para que el
paralelizador entienda y utilice el paralelismo disponible. Calendarización
estática
La generación manual de bloques básicos favorece las computaciones de estructura regular.
-Generación manual de grandes bloques básicos de código.
- No útil para programas
complejos con
representaciones de estructuras
de datos abstractas y complejas.
Las técnicas de optimización enfocadas en la compilación trabajan sobre datos y
código, ambos constantes. Todas las precomputaciones realizadas están orientadas sobre
los datos conocidos al momento de la evaluación. La disponibilidad parcial de los datos y
la precomputación del código definen el concepto del procesamiento de información
incompleta. Existen otras técnicas específicas que manejan niveles más significativos de
incompletitud, tal es el caso del manejo de estructuras incompletas (I-Stmctures) y las
la tabla VI se analizan brevemente tres técnicas orientadas especialmente a funciones. Estas técnicas se enfocan en la evaluación completa o incompleta del código según las exigencias
sobre los resultados que generan y a la parametrización que contienen.
En general, existen muchos enfoques y técnicas orientadas en la realización de
precomputaciones en base a datos constantes y a la evaluación parcial del código, lo cual se
puede globalizar en un procesamiento de información incompleta. En este capítulo se
describieron algunas de las técnicas más comunes que de alguna manera ayudan a
enmarcar la investigación realizada en este trabajo de tesis.
Tabla VI. Formas de aplicar el procesamiento de información incompleta a nivel de funciones.
Técnica Descripción Referencias
Funciones estrictas
(eagerfunction)
La evaluación de una aplicación de la función no termina hasta que el código es evaluado sobre ese argumento. El resultado de la función depende del argumento (llamadas por valor).
(Peterson, 1997)
Funciones suaves
(lazy function)
La evaluación de la función se lleva a cabo según el valor de cierto argumento. Son transformaciones de código a código (llamadas por nombre).
(Launchbury y Peterson, 1996)
Funciones completamente sueves (full laziness)
La evaluación asegura que las subexpresiones en el cuerpo de la función, que no dependen de los argumentos sean evaluadas solamente una vez en una ejecución repetitiva de la función.
II.2 Optimización automática realizada por el compilador.
Cuando se lleva a cabo la optimización de programas con el compilador, el
refinamiento del código se realiza en forma automática, generándose un código intermedio
compacto y eficiente mediante técnicas como las que a continuación se indican (Aho er al.,
1990):
l. Despliegue de constantes (folding).
2. Eliminación de expresiones redundantes.
3. Eliminación de código muerto.
4. Funciones en línea (inlining).
5. Desplegado de ciclos (loop unrolling).
6. Fusión de ciclos.
7. Intercambio de ciclos.
8. Distribución de ciclos.
9. Reducción de esfuerzo.
Estas son nueve de las principales técnicas utilizadas por el compilador, las cuales están
relacionadas directamente con el estilo y la complejidad del código producido por el
programador. Una descripción completa de estas técnicas se encuentra en el libro de
“C0mpilad0res: principios, técnicas y herramientas” (Aho et al., 1990).
Desde el punto de vista del compilador, se realizan optimizaciones de caracter local y
global. En la optimización local, la actividad se concentra básicamente en condiciones
locales dentro un programa fuente, sin contemplar el flujo de la ejecución del programa.
básicos y sobre estos fragmentos se lleva a cabo la optimización. La optimización global se
lleva a cabo mediante la disposición y utilización de los recursos requeridos por todos los
fragmentos de código, así como por las disposiciones oportunas de las localidades de
memoria, etc.
II.2.1 Compiladores optimizadores.
Generalmente los nuevos compiladores poseen las capacidades para optimizar el
código mediante las técnicas descritas en la sección II.2, además de otras técnicas
particulares apegadas a las arquitecturas específicas sobre las cuales corren. En este trabajo
de investigación se utilizan dos compiladores para el lenguaje C: el compilador cc,
propietario de los sitemas de Silicon Graphics y el compilador gcc ajustado a tales
arquitecturas. Ambos compiladores son usados para la compilación en el proceso de
evaluación parcial y en la compilación del código especializado.
El compilador cc forma parte de los compiladores MIPSpi'o para la IRIX celular
(IRIX > 6.4), los cuales son la familia de la cuarta generación de compiladores de la Silicon
Graphics diseñados para la optimización y paralelización de código. Estos compiladores
generan código optimizado de 32 y 64 bits para la MIPS RISC R4000, R4400, R4600>=,
R5000>=, R8000 y los nuevos sistemas RIOOOO Origin bajo el sistema operativo IRIX 6.4
El sistema de compilación MH°Spro incluye las capacidades internas comunes que
realizan todas las optimizaciones y transformaciones escalares y paralelas, además de
compiladores, facilitando la portabilidad de aplicaciones escritas para otras plataformas y
elevando el desempeño de aplicaciones en tiempo de ejecución.
II.2.2 Optimizaciones logradas por los compiladores optimizadores.
Los compiladores MIPSpro realizan un conjunto de optimizaciones de alto nivel y
específicas para ciertas arquitecturas. Las optimizaciones sirven para incrementar el
rendimiento de un amplio rango de aplicaciones científicas y de ingeniería, tales como:
0 Expansión de arreglos a nivel declaración, eliminación de subexpresiones comunes,
propagación de constantes globales, eliminación de código muerto y movimiento de
código global especulativo.
0 Optimizaciones a nivel de ciclos combinando el desplegado de ciclos, intercambio de
ciclos, desplegado y bloqueo, distribución de ciclos, fusión de ciclos, movimiento de
código invariante de ciclos y reducción aritmética.
0 Optimizaciones a nivel de procedimientos tales como optimizaciones de apuntadores,
optimizaciones de punto flotante y procedimientos en línea.
II.3 Paralelización manual y automática.
Un programa secuencial que es diseñado de tal manera que cierta parte de sus
instrucciones pueden ejecutarse por más de un procesador al mismo tiempo, es un
programa en el que los datos que determinan la actividad computacional pueden ser
utilizados sin generar conflictos. La figura 2 muestra la ejecución paralela de un programa.
mismo tiempo, lo que significa que cada procesador ejecuta las mismas o distintas
operaciones sobre un conjunto particular de datos independientes en determinado momento
de la computación.
En cualquier actividad de cómputo, los datos a procesar definen la secuencia de la
computación, permitiendo la secuencialidad ininterrumpida del proceso de ejecución en el
caso de los lenguajes imperativos o la altemancia fluída en los lenguajes declarativos.
Procesador V
3 V I-Iil_o3 ,
ííí._.___._...-í.
2
Hiioz
,_ V
1 ' . -Hilo] ,
_ _ . l ~
0
, ,.Hi1øjo; ii 1
Serial Región paralela Serial
Figura 2. Ejecución paralela de un programa.
La disponibilidad de la información en cada estado del proceso de cómputo permite
no solo la fluidez en la ejecución de procesos, sino también de funciones e incluso de
instrucciones individuales.
Con el fin de facilitar la actividad paralela, tanto los datos como el código pueden
disponerse de tal manera que varios procesadores puedan actuar sobre ellos sin generar
paralela pueden manejarse dos técnicas que facilitan la actividad conjunta de varios
procesadores:
l. Particionamiento de datos.
2. Particionamiento de funciones.
Ambas técnicas son utilizadas, pero generalmente el particionainiento de datos es
más requerido en la programación cotidiana y por tal motivo se describe más ampliamente.
Particionamiento de datos.
Un conjunto de datos puede ser divido en varios segmentos, no específicamente en
términos físicos, sino más bien en cuanto a la asignación de secciones independientes a
cada procesador. El análisis de cada segmento de datos no debe depender del resultado del
procesamiento de otro segmento. En base a esa independencia de operación por parte de los
procesadores, con el particionamiento de datos una respuesta puede ser calculada más
rápidamente, lo mismo que se puede realizar más análisis de programas en un determinado
tiempo.
En la programación paralela cualquier problema que se pretende resolver debe ser
analizado en términos de las posibilidades que existen para lograr la independencia de
datos. En los casos que no existe un paralelismo inherente, es necesario emplear el
algortimo apropiado lograrlo o emplear técnicas sofisticadas de implementaciones de
software y adecuaciones del hardware que permitan la ejecución paralela.
Los problemas que se adaptan mejor al particionamiento de datos están
de señales, análisis estructural y dinámica de fluidos (SGI Doc. Num.
LBTl09-l.O-6.2-S-SD-W).
II.3.1 Formas de paralelizar programas.
Desde el punto de vista de la programación, existen varios métodos de
paralelización de código que se enfocan en evitar y a solucionar los problemas de la
dependecia de datos (SGI Doc. Num. LBTIO9-1.0-6.2-S-SD-W). Una forma simple de
paralelizar es mediante el uso de un lenguaje Power. Un lenguaje Power es una versión
aumentada de un lenguaje de programación común. La programación se realiza con la
sintaxis del lenguaje base y la paralelización del código mediante la sintaxis del lenguaje
Power. De esta manera, se introduce el paralelismo en el código sin afectar la integridad de
la ejecución serial 0 la semántica del lenguaje base. En la supercomputadora SGI Origin
2000 se manejan lenguajes Power para C y para Fortran, denominados Power C y Power
Fortran respectivamente.
La actividad de paralelización del código en forma manual mediante el uso de un
lenguaje Power se realiza en la forma que se muestra en la figura 3. Dado un programa
Prog.c escrito en lenguaje C optimizado en su versión secuencial, el programador agrega
las directivas de paralelización mediante la sintaxis del lenguaje Power, después lo pasa
por el compilador de C (compilador cc que maneja la paralelización) y de esta manera se
obtiene el código ejecutable Prog.exe que es un código paralelo. Para ejecutar el programa
en varios procesadores se establece el ambiente paralelo con la propia sintaxis del lenguaje
Al igual que la optimización de código, también la paralelización puede realizarse
en forma automática. En el caso de la optimización de un programa se utiliza el compilador
para el lenguaje en el que está escrito el código fuente, pero en el caso de la paralelización
se utiliza un analizador del código con capacidades particulares para la paralelización. El
analizador es un preprocesador que realiza la optimización y la paralelización de
programas, reconociendo e implementando el paralelismo de datos de granularidad fina,
además de implementar varias optimizaciones seriales para mejorar el desempeño total
(SGI Doc. Num. O07-0702-O50).
Un analizador tiene dos usos principales: como una herramienta para analizar el
código en cuanto a la dependencia de datos y como una herramienta para el análisis y
paralelización automática de código.
El analizador reconoce e implementa el paralelismo de datos de granularidad fina
mediante la inserción de directivas de multiprocesamiento, lo mismo que usando un
subconjunto de las características de los lenguajes Power. Las optimizaciones seriales son
logradas mediante la realización de optimizaciones generales de código, optimizaciones de
ciclos y de manejo de memoria.
En la SGI Origin 2000 se utiliza un analizador de código fuente secuencial
denominado Power C Analyzer (PCA) para paralelizar en forma automática el código en
lenguaje C. El PCA inserta las directivas de compilación necesarias para la ejecución
paralela en tiempo de compilación (SGI Doc. Num. 007-0702-050). Este analizador
procesa el código fuente después del macroprocesador (cpp), examinando los ciclos antes
código serial, el PCA también trata de optimizar regiones paralelas agregadas
manualmente.
Programa
Pmgc
Programador
Pmgc paralelizado
Compilador
_r 1
ïåïåïff
Entrada L J
dinamica dl
Figura 3. Paralelización manual del código en C mediante el uso de un lenguaje Power. Entrada
estática sl
El PCA es útil en la creación de paralelismo efectivo, garantiza que no existan
errores de paralelización, pero solamente puede analizar y paralelizar ciclos for bajo las
siguientes limitantes:
0 Usando notación explícita para arreglos array[index].
0 No es posible analizar ciclos for usando notación de aritmética de apuntadores *(var +
index).
De igual forma, no es posible analizar ciclos while o do while y no es posible trabajar con
bloques de código (con una actividad particular) que tiene que correr en paralelo.
La actividad de paralelización automática no se describe aquí precisamente para
realizar experimentos con ella, sino más bien para que se puede visualizar el proceso y las
técnicas aplicadas por la herramienta utilizada que realiza dicha actividad. Esto permitirá
hacer una comparación con la paralelización automática lograda con el interprete
desarrollado en este trabajo de tesis. En la figura 4 se observa que la actividad de agregar
directivas de paralelización por parte del programador desaparece en este proceso.
Programa Prog c:
Power C
Analyzer pca
Entrada
estática sl F Ñ
Progexe j Banda
paralelo '
L .J
Entrada dinamica dl
11.4 Beneficios de la optimizacion.
Los primeros beneficios de la optimización son la ejecución más rápida de los
programas y frecuentemente el tamaño más pequeño del código objeto. Sin embargo, la
optimización puede también agilizar el tiempo de desarrollo, por ejemplo, se puede reducir
el tiempo de codificación dejando al optimizador (compilador ó software especial) que
relacione los detalles de programación con la eficiencia del tiempo de ejecución. De esta
manera, el programador puede enfocarse en la definición de la estructura global del
programa sin preocuparse personalmente por la eficiencia en la ejecución del mismo.
ILS Medición del desempeño de programas.
Cualquier optimización que se realice sobre un programa, ya sea manualmente, en
forma automática o mediante el uso de alguna técnica particular de mejoramiento de
código, debe dar como resultado un incremento en la rapidez de procesamiento, lo cual se
define como aceleración. _
Si la optimización la hace el programador, ya sea modificando el algoritmo o
utilizando el potencial (funciones de librerías, etc.) del lenguaje de programación
secuencial, la fórma de medir la acelaración es la siguiente:
Tiempo de ejecución del programa no mejorado (1) aceleración =
La acelaración lograda mediante la evaluación parcial es el principal tema a tratar
en este trabajo de tesis, por tal motivo se estudiarán distintas formas de aplicar la evalución
parcial para lograr altos niveles de aceleración en diferentes ámbitos, tales como la
computación secuencial, el paradigma de programación imperativo, la computación
In EVALUACIÓN PARCIAL.
En la computación tradicional, para que un programa genere un resultado es
necesario que estén disponibles todos los datos de entrada. Los datos deben estar
disponibles en el momento preciso de que sean referenciados en una instrucción, bien sea
que hayan sido inicializados o porque fueron generados por instrucciones previas.
En el capítulo II se describieron las técnicas de optimización y paralelización de
programas, observando claramente que los datos juegan un papel primordial en la
definición del flujo de la computación. En el caso de la optimización del código fuente, en
muchas ocasiones es necesario hacer transformaciones sintácticas para resolver ciertos
conflictos que se presentan con la disponibilidad e integridad de los datos. Respecto a la
paralelización, la dependencia de datos (inherente en algunos algoritmos e
implementaciones) es el principal obstáculo a vencer para lograr ejecuciones rápidas y
resultados confiables.
En este capítulo se introduce una nueva técnica para optimizar programas
denominada evaluación parcial, la cual se centra principalmente en la ejecución parcial de
las instrucciones en base a la disponibilidad de los datos referenciados por las mismas.
Debido a que se realiza una ejecución parcial, el código resultante es una transformación
del código original, el cual requiere de la actividad de un compilador para generar un
resultado final, agregándose de esta forma un paso adicional en el proceso de la generación
En este capítulo se describen los fundamentos de la evaluación parcial, su
aplicabilidad, así como sus alcances y limitaciones.
III.1 Especialización de programas.
Considérese un programa P que tiene dos argumentos S y D y que produce un
resultado R, el cual se expresa de la siguiente manera:
P(S,D) = R
Si solamente el argumento S se conoce antes de la ejecución del programa, se tiene
que S es estático y que D es dinámico. De esta manera, se puede formar un nuevo
programa <P,S> que espera para ser ejecutado hasta que D esté disponible. Este nuevo
programa genera el mismo resultado que el programa original P(S,D):
<P,S>(D) = P(S,D) = R
Cuando se conoce S como entrada para el programa P, las operaciones que
dependen de S pueden ser realizadas antes de que esté disponible D. Por consiguiente, se
puede formar un nuevo programa PS equivalente a <P,S> en el que los cálculos
dependientes de S han sido ya realizados. De esta menera se tiene:
PS (D) = <P,S>(D) = P(S,D) = R
Donde el programa PS es llamado la especialización de P con respecto al parámetro
III.2 Principios de la evaluación parcial.
Generalmente los programadores se enfrentan al dilema entre la generalidad y la
eficiencia de los programas. Por un lado, cuando un programador escribe programas muy
generales, el esfuerzo es mínimo. Por otro lado, si el programador se concentra en
optimizar a mano cuidadosamente para un caso en particular, se puede producir un código
que tiene una ejecución más rápida. Las herramientas de especialización de programas
ofrecen una solución a este dilema, mediante la transformación automática de programas
generales en código especializado eficiente.
La evaluación parcial es una técnica de especialización de programas, la cual toma un programa general P y una parte de sus entradas S (datos estáticos) para realizar todos
los cálculos dependientes de esos datos. El resultado de la ejecución de P respecto a S es un programa residual Pg que contiene las instrucciones que dependen de los datos no
conocidos D (datos dinámicos). El programa generado toma las entradas restantes
resolviendo por completo un problema en particular (Jones et al., 1993). En base a esta
definición se establece que:
Evaluación parcial = Especialización de programas
El programa residual es una transformación del código fuente orignial. La
transformación se expresa en términos de la sustitución de las instrucciones por otras
distintas que expresan la misma actividad computacional. Por la apariencia del programa
residual, la evaluación parcial parece un simple desplegado de constantes, pero se requiere
Cuando la evaluación parcial no puede aplicarse a sustituciones simples de datos constantes
es posible que la estructura del programa original se cambie completamente. De esta
manera, la especialización de programas se convierte en un enfoque general de la
generación de programas. El objetivo de la evaluación parcial es especializar programas
con respecto a cualquier tipo de invariante (valor conocido) detectado en la codificación.
En el sentido más estricto, la evaluación parcial puede considerarse como una
combinación agresiva de la propagación de constantes, funciones en línea, desplegado de
ciclos y la propagación de constantes a nivel interproceso, aplicada a todos los tipos de
datos (incluyendo apuntadores, estructuras y arreglos) y no solamente a datos simples.
La actividad de especialización es realizada por un evaluador parcial denominado
como peval, el cual es un programa que toma dos argumentos como entrada, el programa P
a evaluar y los datos conocidos S para generar un programa especializado Pg particular
(Jones et al., 1993). En la figura 5 se muestran todas las fases de la especialización. En la
primera fase del proceso el evaluador parcial tiene dos entradas, el programa fuente y sus
datos estáticos sl Q S. El resultado de la actividad del evaluador parcial es un programa
residual P_,1, el cual en una segunda fase es procesado junto con los datos dinámicos dl g
D por un compilador. En comparación con el proceso de compilación tradicional, la
especialización de programas agrega la actividad del evaluador parcial como una etapa más
III..2.1 Formulación semántica de la evaluación parcial.
En base a la notación descrita por Mogensen y Sestoft (1996) en su artículo
“Partial evaluation”, la actividad de evaluación parcial puede ser expresada en forma
semántica. Considérese un programa P escrito en un lenguaje L, la notación [PL es usada
para indicar la actividad representada por P. La actividad de P es considerada como la
función de transferencia entre las entradas y las salidas. Supóngase que P tiene n
argumentos de entrada y que es corrido con los argumentos a1, a2,..., a,,. Entonces la
notación HPHL [a¡, a2,...,a,,] representa la salida del programa respecto a estas entradas.
Programa fuente P
Entrada Evaluador
esraflea si
parcial "Peral"
Y Ñ
Entrada Programa í Salida
d¡nám¡Ca dj especializado Psl
¡L .A
Figura 5. Especialización de programas.
En base a esta notación es posible describir el proceso de evaluación parcial en una
forma más precisa. Supóngase que P es un programa con n argumentos, que está escrito en
un lenguaje L y que es procesado por un evaluador parcial denominado peval. Supóngase
momento de la especialización, por lo tanto P es especializado respecto a estos parámetros.
De esta manera, los n - k parámetros son considerados como dinámicos, los cuales estarán
disponibles hasta el tiempo de ejecución. Para una notación más simple se puede considerar
que los primeros k parámetros son estáticos, por lo tanto los a¡, ag, . _ .,ak se denotan como s¡,
s2,...,sk y los aki, 1, ak+2,...,a,, por d1, d2,...,d,,_k. Ahora la actividad completa de P con estas
entradas se expresa como:
ÍPBL [.S`¡, S2,...,Sk, Clj, 6l2,...,(ln_¡¿]
Si el programa P es evaluado parcialmente respecto a sus entradas estáticas se
obtiene el programa P,-es que es el programa residual. Asumiendo que el evaluador parcial
peval está escrito en un lenguaje M, la actividad de especialización es expresada como:
HpevalÍ]M [P, s¡, s2,...,sk] = Pm
Después del proceso de especialización el programa resultante sigue estando en el
lenguaje L. Finalmente el programa residual Pm es ejecutado con los parámetros dinámicos
solamente, obteniendo el resultado:
il-P»-eilit 1611, dz,---,df-i-il
Este resultado obtenido mediante la evaluación parcial es el mismo que se obtiene
mediante el programa original con todas sus entradas. En base a esta afirmación se
establece la ecuación para la actividad del evaluador parcial denominada ecuación de
correctitud:
llpii [S, D] =l llP@W1lllM[P, Sl liz [D] (5)