Avaliação Parcial de Programas Introdução A maior parte dos programas de computador gera uma saída resultante de um processamento que é executado sobre dados que ele recebe como entrada. Entrada Programa Saída Em geral a eficiência de um programa é uma função de seus dados de entrada, ou seja, normalmente o tempo de execução de um programa cresce conforme cresce o tamanho, ou a quantidade, dos dados com os quais o programa é alimentado. Um exemplo de programa de computador Seja a função power(n, x) que calcula o valor de xn. Esta função poderia ser representada por um programa Power com a seguinte forma: n, x Power Definição de Avaliação Parcial de Programas A técnica de obtenção de programas especializados a partir de programas não especializados, com relação à parte da entrada de dados destes últimos, é chamada Avaliação Parcial de Programas. A palavra Avaliação é utilizada porque, para que um programa possa ser especializado, o seu algoritmo precisa ser avaliado a fim de que as computações que dependam somente da parte conhecida da entrada possam ser previamente realizadas. E esta avaliação é Parcial porque o código de um programa não é avaliado com relação a todos os seus dados de entrada, mas apenas com base em parte deles. O objetivo principal da avaliação parcial é o ganho em eficiência. Se parte dos dados de entrada de um programa é conhecida, as estruturas do programa que dependam apenas dessa parte podem ser previamente computadas. O programa especializado conterá apenas o código necessário para processar os dados ainda não conhecidos. xn Nomenclatura Caso fossemos analisar o código do programa Power, este seria mais ou menos assim: n = valor de n lido da entrada; x = valor de x lido da entrada; p = 1; enquanto n > 0 faça p = p * x; n = n - 1; Resultado = p; Esta seqüência finita de passos é denominada o algoritmo de Power. Um Programa Especializado O programa Power está preparado para receber pares de inteiros positivos como dados de entrada. Caso este programa fosse menos flexível, isto é, caso o algoritmo de Power fosse elaborado conhecendo-se um dos valores de entrada, poderia o programa ser mais eficiente? A fim de responder a esta questão, observe uma versão especializada do algoritmo de Power, elaborada para um valor de n sempre igual a 5. Este algoritmo será denominado Power5. x = valor de x lido da entrada; p = 1; p = p * x; p = p * x; p = p * x; p = p * x; p = p * x; Resposta = p; Observe que a variável n não mais aparece no texto do algoritmo de Power5. Como não mais ocorrem testes de parada ou operações aritméticas sobre a variável n, conclui-se que o algoritmo de Power5 é mais eficiente que o algoritmo de Power. Diz-se que Power5 é uma versão de Power especializada com relação a uma parte de sua entrada, neste caso o valor n do expoente da operação xn. Este resultado não é uma coincidência, pois em geral programas especializados com relação a uma parte de sua entrada de dados são mais eficientes que os programas que lhes deram origem. A parte da entrada de um programa conhecida, que será utilizada durante a Avaliação Parcial é denominada Entrada Estática, ao passo que a parte desconhecida é chamada Entrada Dinâmica. Um Avaliador Parcial é um programa que executa Avaliação Parcial de Programas automaticamente. Um Avaliador Parcial recebe como entrada o código de um programa, ou seja, a descrição de seu algoritmo, escrita em uma linguagem de programação, e a entrada estática daquele programa. A saída de um Avaliador Parcial é constituída pelo código especializado obtido a partir do programa de entrada e dos dados estáticos: Código de um Programa Avaliador Parcial Entrada Estática Programa especializado com relação à Entrada Estática A Avaliação Parcial de Programas tem diversas aplicações práticas relacionadas à otimização de programas de computador. Esta técnica é também muito importante em estudos acerca de compilação e geração de compiladores. No restante desta apresentação serão mostrados os resultados conseguidos com a Avaliação Parcial de alguns programas bem conhecidos entre os matemáticos e cientistas da computação. O Avaliador Parcial utilizado chama-se CMIX/II e foi implementado na linguagem C por pesquisadores Dinamarqueses. Universidade Federal de Minas Gerais Departamento de Ciência da Computação Laboratório de Linguagens de Programação Autor: Fernando M. Q. Pereira Coordenadores: Roberto S. Bigonha, Mariza A. S. Bigonha, Vladimir Oliveira de Iorio Avaliação Parcial de Programas Exemplos de Aplicação As técnicas de Avaliação Parcial de Programas possuem diversas aplicações, algumas teóricas, outras práticas. Neste material são mostradas duas das principais aplicações das técnicas de Avaliação Parcial: • Otimização de Programas. • Geração de Compiladores. Otimização de Programas. Otimizar um programa significa melhorar o seu desempenho, seja reduzindo o seu tempo de execução ou os recursos que este programa exige do computador para que possa ser usado. A Avaliação Parcial de um programa muitas vezes permite reduzir o seu tempo de execução na medida em que uma parte do processamento deste programa é realizada durante sua especialização. Neste caso, a Avaliação Parcial é proveitosa quando: T e n T r n T o Te = Tempo de especialização do programa. Tr = Tempo de execução do programa residual (especializado). To = Tempo de execução do programa original (não especializado). n = Número de execuções dos programas original e especializado. Otimizando um algoritmo de interpolação Dada uma tabela de pontos (pares de abscissas e ordenadas), um algoritmo interpolador permite conhecer valores de pontos que não constam naquela tabela. Tal algoritmo geralmente encontra valores intermediários a partir de polinômios que contenham todos os pontos conhecidos da tabela, a partir dos quais as quantidades desconhecidas podem ser inferidas. Algoritmo de Lagrange especializado Este algoritmo foi gerado automaticamente por um Avaliador Parcial a partir do algoritmo mostrado no quadro anterior. números reais: p 0, r 0; p y[0]; p p((z-x[1])/(x[0]-x[1])); r r + p; p y[1]; p p((z-x[1])/(x[0]-x[1])); r r + p; Resposta = r; Análise de desempenho A versão especializada do algoritmo de Lagrange é quase duas vezes mais rápida que a versão original, conforme resultados obtidos via simulação. Na tabela de resultados, a coluna Erro contém a diferença percentual entre os resultados previstos e apurados de fato. CMIX/II: resultados da especialização Tamanho da Tabela 3 5 15 35 65 95 Tempo Original 2.59s 8.58s 114.42s 613.41s 1965.6s 4494.9s Tempo Residual 1.55s 4.51s 59.79s 332.21s 1414.9s 3403.8s Speedup Erro 1.7 1.9 1.9 1.8 1.4 1.3 3% 8% 8% 3% 20% 26% Geração de Interpretadores e de Compiladores. Pode ser demonstrado que é possível gerar interpretadores e compiladores via Avaliação Parcial. Um interpretador recebe um programa qualquer e a entrada de dados desse programa e simula a execução deste programa sobre a entrada. Um compilador é um programa que traduz algoritmos escritos em alguma linguagem de programação para um formato que pode ser executado em algum computador. Um interpretador padrão Programa Fonte Interpretador de Programas Entrada de Dados Algoritmo de Lagrange: Abaixo segue um exemplo de algoritmo de interpolação. Este algoritmo é conhecido como algoritmo de Lagrange, onde x[i] representa a i-ésima abscissa da tabela, y[i] representa a i-ésima ordenada da tabela, m representa o tamanho da tabela e z representa o abscissa que deve ser interpolada: números inteiros: i, j; números reais: p 0, r 0; Para i de 0 até m faça p y[i]; Para j de 0 até m faça se i j então p p((z-x[j])/(x[i]-x[j])); r r + p; Resposta = r; Resultado da Execução Um interpretador obtido via Avaliação Parcial Programa Fonte Interpretador de Programas Avaliador Parcial Entrada de Dados Programa Compilado Um Compilador Padrão Programa Fonte Compilador de Programas Resultado da Execução Entrada de Dados Programa Compilado Resultado da Execução