• Nenhum resultado encontrado

Paralelização automática de laços para arquiteturas multicore

N/A
N/A
Protected

Academic year: 2021

Share "Paralelização automática de laços para arquiteturas multicore"

Copied!
90
0
0

Texto

(1)
(2)

FICHA CATALOGRÁFICA ELABORADA PELA BIBLIOTECA DO IMECC DA UNICAMP

Bibliotecária: Maria Fabiana Bezerra Müller – CRB8 / 6162

Vieira, Cristianno Martins

V673p Paralelização automática de laços para arquiteturas multicore/Cristianno Martins Vieira-- Campinas, [S.P. : s.n.], 2010.

Orientador : Sandro Rigo.

Dissertação (mestrado) - Universidade Estadual de Campinas, Instituto de Computação.

1.Processadores multicore. 2.Arquitetura de computador. 3.Politopos. I. Rigo, Sandro. II. Universidade Estadual de Campinas. Instituto de Computação. III. Título.

Título em inglês: Automatic loop parallelization for multicore architectures

Palavras-chave em inglês (Keywords): 1. Multicore processors. 2. Computer architecture. 3. Polytopes.

Titulação: Mestre em Ciência da Computação

Banca examinadora: Prof. Dr. Sandro Rigo (IC - UNICAMP)

Prof. Dr. Guido Costa Souza de Araújo (IC – UNICAMP)

Prof. Dr. Ricardo Ribeiro dos Santos (Faculdade de Computação - UFMS)

Data da defesa: 08/11/2010

Programa de Pós-Graduação: Mestrado em Ciência da Computação

(3)
(4)

Instituto de Computa¸c˜ao Universidade Estadual de Campinas

Paraleliza¸

ao Autom´

atica de La¸

cos para

Arquiteturas Multicore

Cristianno Martins Vieira

1

Novembro de 2010

Banca Examinadora:

• Prof. Dr. Sandro Rigo (Orientador)

• Prof. Dr. Guido Ara´ujo

Instituto de Computa¸c˜ao (Unicamp)

• Prof. Dr. Ricardo Ribeiro dos Santos

Faculdade de Computa¸c˜ao (UFMS)

• Prof. Dr. Ricardo Pannain (Suplente)

Instituto de Computa¸c˜ao (Unicamp)

• Prof. Dr. Roberto Hexel (Suplente)

Departamento de Inform´atica (UFPR)

1Suporte financeiro de: Bolsa Fapesp (processo 2008/52922-0) 2008–2010.

(5)

Resumo

Embora muitos programas possuam uma forma regular de paralelismo, que pode ser

expressa em termos de la¸cos paralelos, muitos exemplos importantes n˜ao a possuem. Loop

skewing ´e uma transforma¸c˜ao que remodela o espa¸co de itera¸c˜ao dos la¸cos para que seja

poss´ıvel expressar o paralelismo impl´ıcito atrav´es de la¸cos paralelos. Como consequˆencia

da complexidade em se modificar o espa¸co de itera¸c˜ao dos la¸cos, e de poss´ıveis problemas

causados por transforma¸c˜oes deste tipo – como o poss´ıvel aumento na taxa de miss em

caches –, no geral, elas n˜ao s˜ao largamente utilizadas.

Neste projeto, implementamos a transforma¸c˜ao loop skewing sobre o compilador da

lin-guagem C presente no GCC (GNU Compiler Collection), de forma a permitir a assistˆencia

pelo programador. Utilizamos a ferramenta Graphite como base para a implementa¸c˜ao

da otimiza¸c˜ao, apenas representando-a como uma transforma¸c˜ao afim sobre um objeto

matem´atico multidimensional chamado pol´ıtopo.

Mostramos, atrav´es de um estudo detalhado sobre o modelo matem´atico denominado

modelo polit´opico, que la¸cos com estruturas espec´ıficas – perfeitamente aninhados, com

limites e acesso `a mem´oria descritos por fun¸c˜oes afins – poderiam ser representados como

pol´ıtopos, e que transforma¸c˜oes aplicadas a estes seriam espelhadas no c´odigo gerado a

partir desses pol´ıtopos. Dessa forma, qualquer transforma¸c˜ao que possa ser estruturada

como uma transforma¸c˜ao afim sobre um pol´ıtopo, poder´a ser implementada.

Mostramos, ainda, durante a an´alise de desempenho, que transforma¸c˜oes deste tipo s˜ao

vi´aveis e, apesar de algumas limita¸c˜oes impostas pela infraestrutura do GCC, aumentam

relativamente o desempenho das aplica¸c˜oes compiladas com ela – obtivemos um ganho

m´aximo de aproximadamente 115% para o uso de quatro threads em uma das aplica¸c˜oes

executadas. Verificamos o impacto do uso de programas j´a paralelizados manualmente

sobre a plataforma, e obtivemos um ganho m´aximo de 11% nesses casos, mostrando que

ainda aplica¸c˜oes paralelizadas podem conter paralelismo impl´ıcito.

(6)

Abstract

Although many programs present a regular form of parallelism, which can be expressed as parallel loops, many important examples do not. Loop skewing is a transformation that reorganizes the iteration space of loops to make it possible to expose the implicit parallelism through parallel loops. In general, as a consequence of the complexity in modifying the iteration space of loops, and possible problems caused by such changes – such as the possibility of increasing the miss rate in caches –, they are not widely used.

In this work, the loop skewing transformation was implemented on GCC’s C compiler (GNU Compiler Collection), allowing programmer’s assistance. Graphite provides us a basis for implementation of the optimization, just representing it as an affine transforma-tion on a multidimensional mathematical object called polytope.

We show, through a detailed study about the mathematical model called polytope mo-del, that for a very restricted loop structure – perfectly nested, with limits and memory accesses described by affine functions - could be represented as polytopes, and transforma-tions applied to these would be carried by the code generated from these polytope. Thus, any transformation that could be structured as an affine transformation on a polytope, could be added.

We also show, by means of performance analysis, that this type of transformation is feasible and, despite some limitations imposed by the still under development GCC’s in-frastructure for auto-parallelization, fairly increases the performance of some applications compiled with it – we achived a maximum of about 115% using four threads with one of the applications. We also verified the impact of using manually parallelized programs on this platform, and achieved a maximum gain of 11% in these cases, showing that even parallel applications may have implicit parallelism.

(7)

Agradecimentos

Este trabalho se tornou poss´ıvel gra¸cas a muitas pessoas que me ajudaram de diferentes formas. Gostaria de citar todas elas explicitamente, mas sei que dificilmente esta lista estaria incompleta.

Antes de mais nada, eu gostaria de agradecer ao meu orientador Sandro Rigo, que

sempre esteve dispon´ıvel para mim quando eu precisei – n˜ao importava se a raz˜ao fosse

alguma d´uvida t´ecnica, um problema administrativo, ou “apenas” planejando o futuro.

Obrigado, Sandro, por seu apoio em qualquer situa¸c˜ao.

Tamb´em gostaria de agradecer aos membros do Laborat´orio de Sistemas de

Com-puta¸c˜ao da Unicamp: apesar de n˜ao estar presente durante grande parte do

desenvol-vimento deste trabalho, sempre obtive apoio dos colegas dal´ı. Gostaria de agradecer principalmente ao amigo Rodrigo Faveri pelas caronas, conversas, viagens (onde tive a

oportunidade de conhecer n˜ao s´o mais um peda¸co do Brasil, mas sua admir´avel fam´ılia),

enfim, pela paciˆencia para com um colega t˜ao distante de seu lar.

Entretanto, h´a tamb´em muitas outras pessoas que me ajudaram fora dos colegas da

´

area. Sou muito grato a Robson Peixoto, colega de mestrado, com quem eu tive algumas

discuss˜oes frut´ıferas em v´arios t´opicos sobre este projeto. Obrigado, Robson, por sua

colabora¸c˜ao produtiva.

Agrade¸co imensamente aos amigos Marcos Vieira e Rodrigo Tripodi pelas horas dedi-cadas `as revis˜oes e aux´ılio a tradu¸c˜ao de textos, sem os quais eu realmente n˜ao conseguiria

as duas ou trˆes horas de sono por dia (merecidas) em per´ıodos pr´oximos a deadlines.

Agrade¸co tamb´em aos amigos cuiabanos Daniel Vecchiato e Willian Maja, e ao mineiro

Douglas Leite, principalmente pelos grupos de estudo, que nos fortalecia o conhecimento

pelo compartilhamento do mesmo. Obrigado tamb´em aos demais originais companheiros

do ”Bubbles”, que (bom) cresceu tanto durante esses dois anos: Thiago Lechuga e Maria

A. Souza; n˜ao esqueci de vocˆes – s´o pensei em guardar o melhor para o final ;). Espero

sinceramente que nossas vidas, ainda que separadas, sincronizem-se em algum momento e voltemos a nos encontrar =D

Em resumo, gostaria de agradecer a todos os meus amigos, novos e antigos. Vocˆes me

forneceram o equil´ıbrio perfeito entre motiva¸c˜ao e energia para trabalhar, ao mesmo tempo

(8)

que a distˆancia necess´aria disto e uma importante conex˜ao com o mundo al´em do trabalho.

Agrade¸co, particularmente, `a Isaura Souto que, por vezes, tirou-me do confinamento quase

que `a for¸ca, ainda que fosse para “dar uma volta”; suas visitas s˜ao muito agrad´aveis. `A

Amanda Nascimento pelos cavaqueios, pelos conselhos, pela sinceridade, enfim, por ser

uma boa amiga. Tamb´em a Victor Seino e Caroline Barros, colegas de pens˜ao e, acima

disso, amigos, que da mesma forma se dispuseram, principalmente no per´ıodo mais cr´ıtico

do projeto: durante a escrita da disserta¸c˜ao. Obrigado tamb´em aos demais colegas da

pens˜ao; ainda que n˜ao citados explicitamente, tenham a certeza que sou muito grato por

seu companheirismo, amizade e carinho.

Agrade¸co, ainda, ao suporte direto `as minhas atividades de pesquisa dado pela Funda¸c˜ao

de Amparo `a Pesquisa do Estado de S˜ao Paulo, que me permitiu permanecer em dedica¸c˜ao

exclusiva atrav´es de bolsa pelo per´ıodo relativo a este projeto.

Da universidade, gostaria de agradecer primeiramente ao secretariado do Instituto de

Computa¸c˜ao (IC), formado por Fernando Okabe, Fl´avio Luzia, Wilson Bagni, Ademilson

Ramos e Daniel Capeleto: muito obrigado pelo suporte, eficiˆencia e muitas informa¸c˜oes

prestados n˜ao s´o a mim, mas a todos os alunos de gradua¸c˜ao e p´os do IC. Acredito que falo

em nome de todos quando digo que nem imagino nossas vidas acadˆemicas sem seu apoio.

Muit´ıssimo obrigado `as pessoas que tive contato tamb´em junto ao SAPPE/UNICAMP,

em especial Dra. C´elia, que se tornou um conforto e ombro amigo no per´ıodo que precisei.

Gostaria de agradecer tamb´em a todos os demais funcion´arios da Unicamp (m´edicos,

faxi-neiros, seguran¸cas, jardifaxi-neiros, etc.) que se esfor¸cam para manter um ambiente agrad´avel

para n´os, alunos.

Por ´ultimo, mas n˜ao menos importante, obrigado a todos os membros da minha fam´ılia,

principalmente aos meus pais que, de certo, sofreram, assim como eu, por meu tempo

limitado. Obrigado especialmente `a minha m˜ae, que me garantiu a possibilidade de seguir

este caminho. Muito obrigado por seu amor, que tem sido uma fonte infinita de energia para mim.

Agrade¸co a Deus por todos vocˆes.

(9)

“Todas as coisas grandes deste mundo s˜ao feitas por pessoas ingˆenuas

que tˆem uma ideia obviamente imposs´ıvel.”

(10)

Sum´

ario

Resumo v

Abstract vi

Agradecimentos vii

1 Introdu¸c˜ao 1

2 Revis˜ao Bibliogr´afica 4

3 Conceitos B´asicos 11

3.1 Conceitos Alg´ebricos . . . 12

3.1.1 Modelo Polit´opico . . . 14

3.2 Alcan¸cando o Paralelismo . . . 19

3.2.1 An´alise das Dependˆencias . . . 20

3.2.2 Transforma¸c˜oes . . . 24

4 Materiais e M´etodos 29 4.1 GNU Compiler Collection . . . 29

4.2 Graphite . . . 31

4.2.1 Polyhedral Compilation Package . . . 33

4.2.2 GPOLY: GIMPLE representado atrav´es de pol´ıtopos . . . 37

4.3 Autopar . . . 41

4.4 Implementa¸c˜ao . . . 45

5 Experimentos 50

6 Conclus˜oes e Trabalhos Futuros 57

A Tabelas de Resultados 60

(11)

Lista de Tabelas

A.1 Tabela que mostra as medidas de speedup e eficiˆencia para os programas

selecionados no Phoronix Text Suite para a execu¸c˜ao com 4 threads. . . 63

A.2 Tabela que mostra as medidas de speedup e eficiˆencia para os programas

selecionados no Phoronix Text Suite para a execu¸c˜ao com 8 threads. . . 66

A.3 Tabela que mostra as medidas de speedup e eficiˆencia para os programas

selecionados no Phoronix Text Suite para a execu¸c˜ao com 12 threads. . . . 69

(12)

Lista de Figuras

2.1 Classifica¸c˜ao hier´arquica das abordagens para paraleliza¸c˜ao de aplica¸c˜oes . 5

3.1 Representa¸c˜ao gr´afica de espa¸co bidimensional . . . 15

3.2 Exemplo de Loop Statement Tree para o algoritmo 3.3 . . . 17

3.3 Padr˜ao de dependˆencias trabalhadas por loop skewing . . . 26

4.1 Representa¸c˜oes intermedi´arias do GCC . . . 30

4.2 Representa¸c˜oes intermedi´arias do GCC e sua fus˜ao com o Graphite . . . . 31

4.3 Vis˜ao geral dos m´odulos que comp˜oem o Graphite . . . 32

4.4 Representa¸c˜oes em GIMPLE, Pcp e GPOLY . . . 35

4.5 Arquitetura do PCP . . . 36

4.6 Exemplo de detec¸c˜ao de SCoP . . . 38

4.7 Dependˆencias entre os acessos a vetores no algoritmo 4.3(c) . . . 43

5.1 Speedup para as aplica¸c˜oes selecionadas do Phoronix Test Suite . . . 51

5.2 Eficiˆencia para as aplica¸c˜oes selecionadas do Phoronix Test Suite . . . 53

(13)

Lista de Algoritmos

3.1 Estruturas perfeitamente aninhadas de la¸cos . . . 12

3.2 Exemplo de passeio sobre pol´ıtopo da figura 3.1 . . . 15

3.3 N´ucleo da fatora¸c˜ao de Cholesky . . . 17

3.4 Trecho de c´odigo que ilustra dependˆencia de dados . . . 20

3.5 Trecho de c´odigo que ilustra dependˆencia c´ıclica de dados . . . 20

3.6 Exemplo de dependˆencia entre diferentes itera¸c˜oes . . . 22

3.7 Exemplo de dependˆencia entre diferentes itera¸c˜oes . . . 24

3.8 Algoritmo que ilustra dependˆencias de dados em todas as dimens˜oes do la¸co 25 3.9 Algoritmo com diagonal projetada para a dimens˜ao J . . . 26

3.10 Algoritmo ap´os aplica¸c˜ao de loop skewing . . . 27

4.1 Exemplo de c´odigo para constru¸c˜ao de pol´ıtopo . . . 40

4.2 Exemplo de estrutura aninhada de la¸cos com dependˆencia n˜ao muito simples 42 4.3 Exemplos de la¸cos ignorados pelo Autopar . . . 44

4.4 La¸co paralelo reescrito da figura 4.3(c) . . . 44

4.5 Estruturas de la¸co perfeitamente aninhadas geradas a partir de la¸co ani-nhado imperfeito . . . 46

4.6 Exemplo de la¸co perfeitamente aninhado com padr˜ao de dependˆencias com-plexo . . . 46

4.7 La¸co exibido na figura 4.6 ap´os transforma¸c˜oes . . . 47

4.8 Pseudoc´odigo da transforma¸c˜ao loop skewing . . . 49

(14)

Cap´ıtulo 1

Introdu¸

ao

Uma aplica¸c˜ao em software ´e a ponte entre o usu´ario e a plataforma de hardware. Com a

evolu¸c˜ao da tecnologia dos ´ultimos anos, o que vemos ´e uma quantidade cada vez maior

de dados que precisa ser processada em um per´ıodo cada vez menor de tempo. Isso mo-tiva os engenheiros de hardware a buscar avan¸cos em arquiteturas de microprocessadores

e tecnologia de fabrica¸c˜ao, visando criar plataformas capazes de suprir as necessidades

das novas aplica¸c˜oes. At´e recentemente, principalmente no que se refere a processadores

de prop´osito geral (usados em computadores pessoais, por exemplo), o aumento de

de-sempenho era alcan¸cado atrav´es de sucessivos aumentos na densidade de transistores e

frequˆencia do processador. Isto desencadeou s´erios problemas de projeto, principalmente

relacionados a consumo de energia e dissipa¸c˜ao de calor. Al´em disso, mesmo que o tempo

necess´ario para um impulso el´etrico trafegar num processador seja muito pequeno, ele n˜ao

´e igual a zero, o que imp˜oe uma barreira f´ısica como limite para o clock do processador.

Essas limita¸c˜oes obrigaram os projetistas de grandes fabricantes de processadores a buscar

novos modelos de arquitetura de computadores.

Um modelo de computa¸c˜ao j´a conhecido h´a bastante tempo e utilizado principalmente

para aplica¸c˜oes cient´ıficas ´e o processamento em paralelo. Para entender como esse modelo

funciona, basta comparar o processador a um c´erebro humano. ´E sabido que o tempo

gasto para um impulso nervoso transitar entre neurˆonios ´e muito maior que o de um

sinal el´etrico trafegando em um circuito. Por´em, pela existˆencia de milh˜oes de neurˆonios

trabalhando em conjunto, o modelo do c´erebro ´e mais eficiente, sendo, portanto, superior.

Assim, adaptando-se ao modelo do c´erebro, projetistas adicionaram v´arios “neurˆonios

eletrˆonicos” (n´ucleos de processamento) simples e confi´aveis a um mesmo processador.

Esse novo modelo mais especificamente visa combinar elementos m´ultiplos – tais como

sistemas de comunica¸c˜ao, barramentos, caches e unidades l´ogicas e aritm´eticas – em um

´

unico chip, objetivando aumentar o paralelismo em n´ıvel de tarefas [6, 48]. Dessa forma, os novos projetos de processadores e sistemas utilizam multiprocessamento para atingir

(15)

2

os requisitos de desempenho, sem comprometer o projeto com problemas relacionados ao

calor dissipado. Esses novos processadores s˜ao denominados processadores multicore e

tornaram-se os principais produtos de empresas como Intel (Core2Duo e Core2Quad) e

AMD (Opteron e Athlon X2) para computa¸c˜ao de prop´osito geral.

O principal problema ´e que aplica¸c˜oes sequenciais – tamb´em conhecidas como

single-threaded – n˜ao conseguem tirar proveito das caracter´ısticas das novas arquiteturas

multi-core ou multiprocessadas. Em outras palavras, o desempenho de uma aplica¸c˜ao desse tipo

n˜ao melhora simplesmente por executarmos o programa em um processador multicore. E

existe uma grande quantidade de aplica¸c˜oes codificadas de forma sequencial que poderiam

aproveitar-se das vantagens dos sistemas multicore. Muitas aplica¸c˜oes multim´ıdia – como

algoritmos de processamento de imagens, por exemplo – s˜ao naturalmente paraleliz´aveis.

Contudo, a paraleliza¸c˜ao de aplica¸c˜oes n˜ao ´e uma tarefa trivial. O principal problema

´e encontrar o paralelismo na aplica¸c˜ao e efetivamente dividir aquela tarefa de forma a

aproveitar ao m´aximo a m´aquina alvo.

Com o objetivo de atingir um ganho razo´avel de desempenho minimizando a carga

sobre o desenvolvedor, pesquisadores tˆem desenvolvido ferramentas que auxiliam a

para-leliza¸c˜ao [10]. Entretanto, mais interessante seria se linguagens como C/C++, muito

comuns no desenvolvimento de aplica¸c˜oes de prop´osito geral e para sistemas

dedica-dos, oferecessem na pr´opria linguagem mecanismos para ajudar no particionamento da

aplica¸c˜ao. Mais que isso, o compilador, que j´a possui uma sofisticada tecnologia de an´alise

e otimiza¸c˜ao de c´odigo, poderia agregar a paraleliza¸c˜ao como uma de suas otimiza¸c˜oes,

desobrigando ao desenvolvedor a interven¸c˜ao no processo de paraleliza¸c˜ao.

No entanto, o paralelismo introduz muito mais complexidade ao processo de

oti-miza¸c˜ao. Primeiro, porque ´e necess´ario escolher trechos de c´odigo que tragam ganhos reais

`

a aplica¸c˜ao. Na maioria dos casos, dada otimiza¸c˜ao restringe seu dom´ınio de aplica¸c˜ao.

La¸cos, ou fun¸c˜oes recursivas, que tendem a ser partes de c´odigo executadas in´umeras

vezes, s˜ao fortes candidatos `a paraleliza¸c˜ao. Ainda assim, por influˆencia de limitantes,

como dependˆencias nos acessos aos dados, nem todos estes trechos de c´odigo podem ser

aproveitados.

Al´em disso, encontrar paralelismo atrav´es da an´alise est´atica do c´odigo nem sempre

nos d´a uma vis˜ao concreta dos acessos aos dados realizados durante a execu¸c˜ao de uma

aplica¸c˜ao. O uso de apontadores ou acessos irregulares a vetores (como o uso de vetores

para indexar vetores) deturpam os resultados das an´alises de dependˆencias, e o c´odigo,

muitas vezes independente, n˜ao pode ser paralelizado; al´em disso, na maioria dos casos o

paralelismo n˜ao est´a explicitado na aplica¸c˜ao. Nestes casos, ´e necess´aria uma boa an´alise

de dependˆencias por parte do compilador, ou um bom processo de paraleliza¸c˜ao deveria

ser capaz de detectar o paralelismo impl´ıcito.

(16)

3

skewing, uma transforma¸c˜ao que pode reorganizar as itera¸c˜oes de la¸cos perfeitamente

ani-nhados de forma a mover as dependˆencias de dados para os la¸cos mais externos. As

prin-cipais vantagens desta abordagem s˜ao o tratamento do paralelismo, mesmo que impl´ıcito

na aplica¸c˜ao, e a garantia da independˆencia das itera¸c˜oes nos la¸cos internos, deixando-os

completamente paraleliz´aveis.

Neste projeto, uma abordagem baseada no modelo matem´atico denomidado modelo

polit´opico foi adotada para a implementa¸c˜ao de transforma¸c˜oes sobre o c´odigo

inter-medi´ario do GCC. Primeiramente, um estudo aprofundado sobre as aplica¸c˜oes do modelo

polit´opico foi realizado. Fundamentalmente, este modelo permite a representa¸c˜ao de um

conjunto de restri¸c˜oes por objetos matem´aticos multidimensionais chamados poliedros.

Certas tranforma¸c˜oes (como rota¸c˜ao e transla¸c˜ao) podem ser aplicadas a esses objetos,

desde que elas possam ser representadas por um conjunto de opera¸c˜oes descritas por

fun¸c˜oes afins. Um estudo sobre representa¸c˜ao de hierarquia e dependˆencias presentes em

estruturas aninhadas de la¸cos foi realizado, a fim de representar trechos de c´odigo em

al-guma linguagem de programa¸c˜ao atrav´es de pol´ıtopos, garantindo que exista a tradu¸c˜ao

inversa (de pol´ıtopo para a linguagem de programa¸c˜ao). Ao representar transforma¸c˜oes

complexas (como loop skewing, por exemplo) por um conjunto de transforma¸c˜oes sobre

pol´ıtopos, esse tipo de transforma¸c˜ao pode ser facilmente aplicado aos la¸cos represent´aveis

pelo modelo. Essa disserta¸c˜ao, ent˜ao, foca na aplica¸c˜ao de transforma¸c˜oes que exp˜oem

paralelismo sobre la¸cos aninhados utilizando o modelo polit´opico como base.

O restante do texto est´a organizado como se segue: o pr´oximo cap´ıtulo descreve

tra-balhos relacionados ao tema deste projeto. O cap´ıtulo seguinte fornece alguns conceitos

b´asicos; no cap´ıtulo 4, s˜ao apresentados os materiais e a solu¸c˜ao implementada sobre o

GCC (GNU Compiler Collection) para a paraleliza¸c˜ao de aplica¸c˜oes desenvolvida neste

trabalho; os resultados das execu¸c˜oes de programas reais compilados com a nova solu¸c˜ao

e sua an´alise s˜ao apresentados no cap´ıtulo 5 para a valida¸c˜ao da solu¸c˜ao; o cap´ıtulo

se-guinte realiza as considera¸c˜oes finais e exp˜oe trabalhos futuros sobre o tema; e, por fim,

(17)

Cap´ıtulo 2

Revis˜

ao Bibliogr´

afica

Devido a limitantes f´ısicos para o tamanho e temperatura dos circuitos, avan¸cos recentes

em microarquitetura tˆem na replica¸c˜ao de n´ucleos de processamento uma esperan¸ca para

ganho de desempenho. Atualmente, mesmo sistemas embarcados j´a possuem

processado-res formados por mais de um n´ucleo [32].

Al´em desses processadores aumentarem o paralelismo permitindo que uma maior

quan-tidade de dados seja processada por vez, a proximidade dos n´ucleos de processamento

tamb´em minimiza o tempo de comunica¸c˜ao entre eles. Este fator ´e uma importante

caracter´ıstica das novas arquiteturas: enquanto v´arias aplica¸c˜oes distintas podem ser

exe-cutadas nos v´arios n´ucleos presentes no processador, caso uma aplica¸c˜ao paralela seja

executada, ela tamb´em deve tirar proveito dos v´arios n´ucleos. Para tal, quando alguma

sincroniza¸c˜ao se fizer necess´aria, haver´a a comunica¸c˜ao entre os n´ucleos, que n˜ao ocorre

numa vers˜ao serial da mesma aplica¸c˜ao. A comunica¸c˜ao, neste caso, representa apenas

overhead e, portanto, ´e desej´avel gastar o m´ınimo de tempo para que ela ocorra.

Mas, ao contr´ario do que acontecia com o aumento do desempenho do sistema ao

aumentar a frequˆencia do processador, por exemplo, a mudan¸ca de um processador de

n´ucleo simples para um com v´arios n´ucleos n˜ao ´e o bastante para diminuir o seu tempo de

resposta. Se, por um lado, essas novas arquiteturas aumentam a taxa de throughput1 [40],

permitindo o processamento de v´arias tarefas simultaneamente, para aplica¸c˜oes que n˜ao

fazem uso intensivo de threads, ou sistemas que n˜ao s˜ao multitarefa, n˜ao haver´a qualquer

diferen¸ca no tempo de execu¸c˜ao.

Para que haja um aproveitamento real das aplica¸c˜oes de prop´osito geral, h´a duas

abordagens poss´ıveis: o programador reformula o c´odigo do programa para que ele usufrua

os m´ultiplos n´ucleos de processamento, seja atrav´es de paralelismo de threads, processos,

tarefas, etc., usando bibliotecas que exigem sincroniza¸c˜ao e divis˜ao de tarefas expl´ıcita; ou

o pr´oprio hardware, ou uma interface com o mesmo (como o compilador, por exemplo),

1Taxa que relaciona o n´umero de tarefas que entram com as tarefas que saem do sistema.

(18)

5

automaticamente reconheceria partes potencialmente paralelas do c´odigo, selecionando-as

para execu¸c˜ao concorrente. Uma classifica¸c˜ao hier´arquica para as abordagens discutidas

aqui pode ser vista na figura 2.1. A abordagem adotada neste projeto seria denominada

solu¸c˜ao autom´atica por software assistida pelo programador seguindo esta classifica¸c˜ao.

Paralelização

Manual + custosa

Automática

Solução por HW Combinada a SW (API)

Reprojeto de HW ñ flexível ñ escalável Solução por SW Semiautomatizada induzida Modelagem/Programação retreino de programadores Modificações em Compiladores Stand-alone auto-suficiente Assistida autoparallel.mmap - 5/9/2010 - Mindjet

Figura 2.1: Classifica¸c˜ao hier´arquica das abordagens para paraleliza¸c˜ao de aplica¸c˜oes. Na

figura, os acrˆonimos HW e SW fazem referˆencia a hardware e software, respectivamente.

´

E importante frisar que a distin¸c˜ao entre paraleliza¸c˜ao semiautomatizada e assistida se

d´a pelo grau de interferˆencia do programador: na primeira delas, o programador indica

os trechos de c´odigo a serem paralelizados, enquanto na segunda, o programador recebe

informa¸c˜oes sobre trechos onde a autoparaleliza¸c˜ao n˜ao pˆode ser aplicada com sucesso, e

este poder´a modificar o c´odigo para permitir sua aplica¸c˜ao.

A primeira alternativa claramente ´e a mais custosa, uma vez que anos de software

legado deveriam ser reprojetados para fazer uso dos recursos de hardware atuais. Neste

caso, a paraleliza¸c˜ao autom´atica n˜ao requereria tanto esfor¸co para realizar a mesma

ta-refa. Nesta vertente, alguns estudos sugerem mudan¸cas no hardware, provendo suporte

a opera¸c˜oes que permitam extrair o m´aximo do potencial dos processadores. Em [8], por

exemplo, um modelo de arquitetura multicore heterogˆenea em conjunto com uma API2

2Do inglˆes, Application Programming Interface ´e uma interface que um programa implementa para

(19)

6

espec´ıfica s˜ao discutidos como uma poss´ıvel solu¸c˜ao para problemas de sincroniza¸c˜ao

en-tre as threads de um programa. O processador seria formado por um n´ucleo principal,

onde a por¸c˜ao serial do programa executaria, e v´arios n´ucleos menores especializados em

processamento num´erico e sem mecanismos de preemp¸c˜ao, que seriam alocados a tarefas

paralelas.

Tamb´em, em [46] ´e apresentada a t´ecnica conhecida como Thread-Level Data

Specula-tion3 (TLDS), que representa o uso de especula¸c˜ao sobre dados na mem´oria para permitir

a sobreposi¸c˜ao da execu¸c˜ao de trechos interdependentes de c´odigo. Sua unidade m´ınima

de execu¸c˜ao ´e a thread, e, caso algum acesso `a mem´oria viole alguma das regras b´asicas

do modelo, seus c´alculos s˜ao descartados e a execu¸c˜ao daquela thread ´e reiniciada. Neste

artigo, pequenas modifica¸c˜oes no hardware (como uma extens˜ao do protocolo de coerˆencia

de cache para permitir a detec¸c˜ao de viola¸c˜ao de dependˆencias entre os processadores)

s˜ao sugeridas para tornar a t´ecnica mais agressiva. Ainda, em [47] o mesmo autor discute

o desempenho da implementa¸c˜ao de TLDS e sugere uma implementa¸c˜ao de algoritmo em

hardware para sincroniza¸c˜ao dinˆamica entre as threads.

Por outro lado, [51] sugere uma reformula¸c˜ao da arquitetura para processadores

mul-ticore, apresentando o processador Voltron como proposta, que adiciona `a arquitetura

convencional duas caracter´ısticas principais: uma rede de intercomunica¸c˜ao entre os

ban-cos de registradores dos n´ucleos, que aparentemente habilitaria sincroniza¸c˜ao entre os

n´ucleos atrav´es de uma comunica¸c˜ao com baixa latˆencia; e suporte a dois modos de

execu¸c˜ao, nos quais os n´ucleos poderiam ter o comportamento de um multicluster VLIW

(modo acoplado), explorando basicamente ILP (Instruction-Level Parallelism), ou

explo-rar paralelismo de gr˜aos mais grossos (modo desacoplado), do tipo TLP (Thread-Level

Parallelism) ou LLP (Loop-Level Parallelism).

Nenhuma dessas mudan¸cas, entretanto, ´e trivial, exigindo um reprojeto dos

proces-sadores para cada nova t´ecnica. Desse modo, al´em de n˜ao escal´avel, a solu¸c˜ao dada por

hardware ´e inflex´ıvel[17]. A paraleliza¸c˜ao por software, ent˜ao, claramente se torna mais

vi´avel.

Entretanto, apesar de haver uma longa hist´oria envolvendo paraleliza¸c˜ao de aplica¸c˜oes

cient´ıficas, existem alguns problemas ainda intrat´aveis – decorrentes de dependˆencias

com-plexas, por exemplo – al´em das diferen¸cas aparentes na estrutura de aplica¸c˜oes cient´ıficas

e aquelas de prop´osito geral, o que excluiria um grande n´umero de t´ecnicas geralmente

aplicadas `as primeiras, mas n˜ao t˜ao pr´oximas em contexto das ´ultimas. Geralmente,

ent˜ao, opta-se por aplica¸c˜ao de uma paraleliza¸c˜ao semiautomatizada (ou induzida), na

qual indica-se a um preprocessador onde o paralelismo pode ser explorado, e como se

3TLDS trata-se de uma varia¸ao de Thread-Level Speculation (TLS), onde os valores dos dados

pre-sentes na mem´oria podem ser previstos. Em TLS, ´e permitida a execu¸c˜ao paralela de threads cujos c´odigos s˜ao potencialmente interdependentes, mas os resultados de sua execu¸c˜ao ´e apenas considerado caso nenhuma dependˆencia tenha sido violada.

(20)

7

comportam as dependˆencias naquele c´odigo, e este geraria automaticamente o c´odigo

pa-ralelo para a aplica¸c˜ao; outra alternativa ´e abordar a paraleliza¸c˜ao de casos espec´ıficos,

onde pode-se determinar a existˆencia de dependˆencias (como impor a restri¸c˜ao de

para-lelizar c´odigos com vetores, mas n˜ao com listas encadeadas, por exemplo).

Para auxiliar na paraleliza¸c˜ao semiautom´atica, existem algumas API que

implemen-tam o paralelismo e podem ser invocadas para iniciar e finalizar uma regi˜ao paralela

de c´odigo (onde as unidades processantes deveriam ser replicadas). Em [6], por

exem-plo, ´e apresentado o Multicore Framework, uma API para programa¸c˜ao de processadores

multicore heterogˆeneos. Esta API provˆe uma vis˜ao abstrata do hardware com rela¸c˜ao `a

computa¸c˜ao de conjuntos de dados multidimensionais. Em [2] ´e apresentada uma

biblio-teca de primitivas paralelas de c´odigo aberto chamada SWARM (Software and Algorithms

for Running on Multicore). Um conjunto de algoritmos, incluindo ordena¸c˜ao, sele¸c˜ao e

m´axima parsimˆonia, foi implementado utilizando esta biblioteca para avaliar sua facilidade

de uso e desempenho (apesar de sua implementa¸c˜ao ainda n˜ao encontrar-se totalmente

otimizada). ´

E discutido em [25] o Multicore Communication API (MCAPI), a especifica¸c˜ao de um

framework para constru¸c˜ao de algoritmos paralelos para processadores multicore baseada

em passagem de mensagens. O objetivo ao desenvolver essa especifica¸c˜ao era torn´

a-la um padr˜ao para arquiteturas multicore heterogˆeneas, uma vez que pThreads[43] foi

projetado para ambientes multiprocessados homogˆeneos – e a maioria das implementa¸c˜oes

OpenMP[11] s˜ao baseadas em pThreads. De maneira semelhante, o uso de frameworks

que implementam o padr˜ao MPI (Message Passing Interface)[45] n˜ao foram projetados

para essas arquiteturas, e poder˜ao n˜ao usufruir completamente de seus recursos.

Em alguns casos, mudan¸cas no pr´oprio modelo de programa¸c˜ao foram sugeridas, como

em [4], que oferece um sistema baseado em C para programa¸c˜ao paralela multithreaded.

Este sistema permite a cria¸c˜ao de threads a partir de um conjunto de comandos, e escalona

tarefas entre elas baseado em work-stealing.

Existem, ainda, ferramentas que auxiliam na escrita do c´odigo para ambas as

aborda-gens de paralelismo (autom´atica e manual): em [27] ´e apresentado o iPat/OMP, uma

ferra-menta para assistˆencia interativa `a paraleliza¸c˜ao que escolhe a correta diretiva OpenMP

para la¸cos a partir da assistˆencia do programador, enquanto em [22] ´e realizada uma

an´alise entre diferentes blocos b´asicos, e c´odigo alvo apropriado para a abordagem de

passagem de mensagens ´e gerado. O principal objetivo de tais ferramentas ´e tornar o

processo de paraleliza¸c˜ao o mais pr´oximo poss´ıvel da automatiza¸c˜ao. Em geral, ambas

as abordagens s˜ao melhor aplicadas a casos com caracter´ısticas espec´ıficas. Algumas

su-gest˜oes a mudan¸cas nos padr˜oes dessas abordagens, tornando a automatiza¸c˜ao de seu

uso mais gen´erica, como em [21], que prop˜oe algumas t´ecnicas de otimiza¸c˜ao para

(21)

8

ser encontradas na literatura.

Em comum a todas as abordagens mencionadas, a paraleliza¸c˜ao autom´atica

concentra-se em minerar partes de c´odigo que apresentam potencial para o paralelismo. Fun¸c˜oes

recursivas, por exemplo, geralmente apresentam algoritmos com estrat´egia do tipo

“di-vidir e conquistar”. Caso n˜ao existam dependˆencias, c´odigos baseados nesse tipo de

estrat´egia podem ser facilmente paralelizados [23]. Na maioria dos casos, no entanto,

compiladores paralelizantes focam em la¸cos, por potencialmente executarem por longos

per´ıodos de tempo, e possu´ırem um padr˜ao de acesso aos dados entre suas itera¸c˜oes.

Al-gumas aplica¸c˜oes, tais como jogos, som, v´ıdeo e aplica¸c˜oes cient´ıficas usam intensamente

opera¸c˜oes sobre conjuntos de dados em la¸cos, por exemplo.

Devido `a incerteza quanto `a independˆencia dos dados na autoparaleliza¸c˜ao, ´e bastante

comum o uso de heur´ısticas, que n˜ao garantem a solu¸c˜ao ´otima, mas produzem

rapida-mente um bom c´odigo paralelo na maioria dos casos. TLS, j´a citada anteriormente, ´e um

bom exemplo deste tipo de heur´ıstica. Em especial, ´e poss´ıvel ver em [39] o uso de TLS

para permitir a la¸cos aninhados o usufruto do potencial de processadores multicore. A

implementa¸c˜ao apresentada neste artigo n˜ao exigia modifica¸c˜oes no hardware atual, mas

obteve cerca de 15% de ganho, na m´edia, no tempo de execu¸c˜ao dos programas testados.

Outro uso de especula¸c˜ao na tentativa de driblar o problema das dependˆencias ´e

discutido em [35], onde, para la¸cos com dependˆencias, ´e escolhido o n´umero de itera¸c˜oes

a serem executadas em paralelo, considerando a probabilidade de ocorrer a viola¸c˜ao de

alguma dependˆencia naquele conjunto de itera¸c˜oes. Neste caso, os resultados tamb´em

mostraram ganho de cerca de 12% em m´edia.

Outro uso de especula¸c˜ao para maximizar o uso de multicore pode ser visto em [52],

onde algumas transforma¸c˜oes para la¸cos s˜ao apresentadas para diminuir a influˆencia das

dependˆencias sobre o desempenho da aplica¸c˜ao de TLS. S˜ao aplicadas transforma¸c˜oes,

tais quais fiss˜ao especulativa de la¸cos e isolamento de dependˆencias pouco frequentes,

mas ´e importante notar que a aplica¸c˜ao de transforma¸c˜oes que isolam as dependˆencias

(e, portanto, exp˜oem paralelismo) ajudam a aumentar o desempenho de t´ecnicas para

autoparaleliza¸c˜ao.

Uma aplica¸c˜ao mais interessante de especula¸c˜ao ´e encontrada em [15], onde ´e discutida

uma solu¸c˜ao baseada em alguns princ´ıpios do modelo polit´opico para a paraleliza¸c˜ao de

estruturas espec´ıficas de la¸cos: la¸cos do tipo for aninhados em um la¸co do tipo while que

itera sobre uma condi¸c˜ao convergente (estrutura presente em grande parte de aplica¸c˜oes

num´ericas). Neste caso, o pr´oprio n´umero de itera¸c˜oes do la¸co externo deve ser

especu-lado. No entanto, al´em de bastante espec´ıfico, o artigo deixa claro que nenhum teste foi

executado para verificar a solu¸c˜ao – trata-se apenas de um conceito – e n˜ao foi encontrado

(22)

9

Outra heur´ıstica adotada atualmente tem sido a especula¸c˜ao de traces de execu¸c˜ao4.

Em trabalhos como [48], traces s˜ao somente utilizados para auxiliar na visualiza¸c˜ao da

intera¸c˜ao entre m´ultiplas threads, enquanto em [7] h´a a implementa¸c˜ao de um modelo de

execu¸c˜ao paralelo baseado em traces. Na discuss˜ao sobre os resultados, a aplica¸c˜ao da

t´ecnica apresentou resultados muito parecidos com a TLDS.

Todavia, em determinados contextos, ´e poss´ıvel paralelizar automaticamente o c´odigo

por aplica¸c˜ao de procedimentos algor´ıtmicos, ao inv´es de usar heur´ısticas; a t´ecnica

deno-minada modelo polit´opico, por exemplo, que pode ser aplicada para otimiza¸c˜oes de la¸cos

com acesso `a mem´oria, limitantes e incremento descritos por fun¸c˜oes afins. Em [24] e [34]

´e aplicada a transforma¸c˜ao chamada tiling sobre la¸cos perfeitamente aninhados5. Em [5],

ainda, temos a cria¸c˜ao de um preprocessador que recebe um c´odigo em C e devolve outro

c´odigo tamb´em em C com tiling aplicada a todos os la¸cos que sejam poss´ıveis.

Em especial, em [37] s˜ao relatados os resultados dos testes realizados sobre o

com-pilador autoparalelizador OSCAR, avaliando seu desempenho sobre dois processadores

de quatro n´ucleos (o FR1000, com n´ucleos VLIW6, desenvolvido pela Fujitsu Ltda.; e o

RP1, com n´ucleos SH4A, desenvolvido num cons´orcio entre Renesas Technology Corp.,

Hitachi Ltda. e Waseda University). Ao contr´ario do trabalho desenvolvido neste projeto,

o OSCAR aproveita-se de informa¸c˜oes espec´ıficas da arquitetura para otimizar o c´odigo,

o que garante melhores resultados, mas ao custo de exigir uma sele¸c˜ao – e, talvez,

reim-plementa¸c˜ao – de otimiza¸c˜oes ´unica para cada nova arquitetura cujo suporte venha a ser

adicionado.

Ainda outro fator est´a relacionado com a qualidade do c´odigo gerado pelo compilador:

sendo que a maioria destas transforma¸c˜oes ´e implementada como otimiza¸c˜oes sobre o

c´odigo fonte, ´e importante notar que, a depender da aplica¸c˜ao, a ordem de otimiza¸c˜oes

de la¸cos ´e ´otima [49]. Compiladores mais simples apenas imp˜oem determinada ordem

na aplica¸c˜ao das otimiza¸c˜oes, enquanto outros utilizam a t´ecnica conhecida como

gerar-e-testar, onde todos os arranjos sobre otimiza¸c˜oes s˜ao testados; o primeiro claramente ignora

um ganho em potencial no desempenho das aplica¸c˜oes compiladas, enquanto o segundo

perde muito tempo na gera¸c˜ao do c´odigo. Em [9], utilizam-se t´ecnicas de aprendizado de

m´aquina para constru¸c˜ao de um compilador que escolha a melhor ordem para a aplica¸c˜ao

de otimiza¸c˜oes.

Demais disto, v´arios estudos sobre como melhor aproveitar-se do potencial das

arqui-4Originalmente desenvolvido para aumentar os blocos cont´ıguos de instru¸oes para m´aquinas VLIW

(Very Long Instruction Word ), um trace trata-se de um poss´ıvel caminho tomado ao longo de um con-junto de branches no c´odigo. No processo de otimiza¸c˜ao, as decis˜oes mais comumente tomadas sobre branches s˜ao assumidas sempre tomadas em uma c´opia do c´odigo, que possui uma maior oportunidade de otimiza¸c˜ao (uma vez que os branches n˜ao se fazem necess´arios aqui).

5Um conjunto de la¸cos ´e dito estar perfeitamente aninhado se, para cada la¸co, ou ele possui exatamente

um la¸co em seu corpo, ou ele ´e o la¸co mais interno e possui instru¸c˜oes diferentes de um la¸co no seu interior.

(23)

10

teturas multicore tˆem sido realizados. Uma vis˜ao geral de quanto se tem desenvolvido

nesta ´area pode ser obtida em [30]. Nesta mesma pesquisa, o autor chama a aten¸c˜ao

para o fato que as linguagens de programa¸c˜ao mais utilizadas em aplica¸c˜oes comerciais

(C, C++, Java, etc.) foram escritas com base em paradigmas seriais e a paraleliza¸c˜ao

automatizada a partir das mesmas n˜ao ´e uma tarefa trivial.

Em se tratando especificamente de transforma¸c˜oes sobre la¸cos aninhados, muitas

abor-dagens tˆem sido implementadas e introduzidas a compiladores. A grande maioria delas

simplesmente reestrutura o c´odigo-fonte, devolvendo um c´odigo na mesma linguagem com

a transforma¸c˜ao aplicada aos la¸cos. ParaScope[16] e Polaris[3], por exemplo, s˜ao

para-lelizadores fonte-a-fonte para Fortran baseados em dependˆencias. Entretanto, s˜ao

ferra-mentas fundamentalmente acadˆemicas e, portanto, sem muito contato com programas

reais.

O PIPS [26] ´e um dos mais completos compiladores com reestrutura¸c˜ao de la¸cos,

imple-mentando an´alise polit´opica e transforma¸c˜oes, al´em de an´alise interprocedural. Ele utiliza

uma ´arvore sint´atica estendida com anota¸c˜oes para representar pol´ıtopos, dificultando um

pouco a implementa¸c˜ao de transforma¸c˜oes. O compilador MARS[38] unifica as id´eias de

transforma¸c˜oes de la¸cos baseadas em dependˆencias com otimiza¸c˜oes de armazenamento

de dados. No entanto, sua representa¸c˜ao intermedi´aria n˜ao ´e capaz de capturar todas as

informa¸c˜oes de la¸cos; somente dom´ınios e fun¸c˜oes de acesso s˜ao represent´aveis, n˜ao sendo poss´ıvel o armazenamento do escalonamento. O Graphite[41], por sua vez, objetiva ser

uma ferramenta modular de reestrutura¸c˜ao de c´odigo em representa¸c˜ao intermedi´aria, de

uso geral. Por ter sido constru´ıda inicialmente sobre uma ferramenta de produ¸c˜ao (GCC),

´e poss´ıvel notar que pretende-se aplic´a-lo a programas reais, e n˜ao apenas mantˆe-lo como

ferramental acadˆemico.

Este projeto utilizou o Graphite como base para a implementa¸c˜ao de transforma¸c˜oes

afins sobre la¸cos a fim de tornar suas itera¸c˜oes independentes. Para la¸cos nos quais n˜ao

foi poss´ıvel aplicar a t´ecnica, mensagens a partir do otimizador podem ser habilitadas

para auxiliar o programador a descobrir quais la¸cos estavam sendo reestruturados. Al´em

disso, uma an´alise do uso da ferramenta em aplica¸c˜oes reais mostrou que o desempenho

(24)

Cap´ıtulo 3

Conceitos B´

asicos

Programas passam a maior parte de seu tempo de execu¸c˜ao efetuando a mesma opera¸c˜ao

sobre diferentes conjuntos de dados. Logo, as estruturas que realizam o controle desta repeti¸c˜ao s˜ao pass´ıveis de serem paralelizadas. La¸cos e fun¸c˜oes recursivas s˜ao as principais raz˜oes de repeti¸c˜ao de c´odigo; essas estruturas geram, durante suas execu¸c˜oes, m´ultiplas

instˆancias das instru¸c˜oes em seus corpos.

Este trabalho concentra-se nas estruturas de la¸cos, representando-as atrav´es de

obje-tos matem´aticos, conhecidos por pol´ıtopos1. Ap´os a aplica¸c˜ao de um conjunto de

trans-forma¸c˜oes sobre esses pol´ıtopos, outra estrutura de la¸cos ´e gerada, otimizada para algum

crit´erio (c´odigo mais compacto, menor consumo de mem´oria, ou exposi¸c˜ao de

parale-lismo, por exemplo). Em especial, esta t´ecnica ´e somente aplic´avel a estruturas de la¸cos

perfeitamente aninhadas.

Defini¸c˜ao 1 (Aninhamento perfeito). Um conjunto de la¸cos ´e dito estar

perfeita-mente aninhado se, para cada la¸co, ou ele possui exataperfeita-mente um la¸co em seu corpo, ou ele ´e o la¸co mais interno e possui instru¸c˜oes diferentes de la¸cos no seu interior.

No algoritmo 3.1(a) ´e poss´ıvel visualizar um exemplo de la¸co aninhado. Esta defini¸c˜ao,

no entanto, pode ser relaxada, como foi implementada neste projeto, para que estruturas

de la¸cos como mostrada na figura 3.1(b) tamb´em sejam consideradas perfeitamente

ani-nhadas. Para isso, basta considerar o la¸co mais interno na figura (cuja vari´avel de indu¸c˜ao

´e k) como um bloco de instru¸c˜oes pertencente ao corpo do la¸co um n´ıvel acima. Dessa

forma, o la¸co de ´ındice j passa a ser o la¸co mais interno, e o aninhamento ´e perfeito.

Neste cap´ıtulo, ser˜ao discutidos conceitos b´asicos de ´algebra e paralelismo para auxiliar

no entendimento do que foi desenvolvido neste trabalho.

1Ou politopo.

(25)

3.1. Conceitos Alg´ebricos 12

Algoritmo 3.1: Estruturas perfeitamente aninhadas de la¸cos. O exemplo em (a)

segue a defini¸c˜ao 1, onde instru¸c˜oes diferentes de la¸cos somente aparecem no interior

o la¸co mais interno. Em (b), apenas os dois primeiros la¸cos (cujas vari´aveis de

indu¸c˜ao s˜ao i e j) formam uma estrutura perfeitamente aninhada, e o terceiro la¸co

pode ser visto como uma senten¸ca pertencente ao corpo do segundo la¸co. (a) for i ← 1 to 10 do for j ← i to 10 do for k ← i to 10 do S: a ← a + b ∗ c T: b ← b ∗ b end end end (b) for i ← 1 to 10 do for j ← i to 10 do T: b ← b ∗ b for k ← i to 10 do S: a ← a + b ∗ c end end end

3.1

Conceitos Alg´

ebricos

Por restri¸c˜oes presentes na representa¸c˜ao do modelo matem´atico a ser utilizado neste

pro-jeto, ´e exigido que os la¸cos cumpram alguns requisitos [19, 31]; esses la¸cos s˜ao conhecidos

como La¸cos de Controle Afim (Affine Control Loops, ACL).

Defini¸c˜ao 2 (Fun¸c˜ao linear). Uma fun¸c˜ao d0-dimensional f com d argumentos v1, . . . , vd

´e linear se ela pode ser expressa da seguinte forma:

linear f (v) = Mfv, onde v =    v1 .. . vd   e Mf ∈ R

d0×d ´e uma matriz com d0 linhas e d colunas.

No contexto do conjunto de ´ındices, s´o se faz interessante tratar com matrizes inteiras,

ou seja, Mf ∈ Zd

0×d

.

Defini¸c˜ao 3 (Fun¸c˜ao afim). Uma fun¸c˜ao d0-dimensional f com d argumentos v1, . . . , vd

´e af im se ela pode ser expressa da seguinte forma:

af im f (v) = Mfv + f0, onde v =    v1 .. . vd   , Mf ∈ R

d0×d ´e uma matriz com d0 linhas e d colunas, e f

0 ∈ R. Ou

(26)

3.1. Conceitos Alg´ebricos 13

Da mesma forma, para o problema da representa¸c˜ao do espa¸co de ´ındices do la¸co,

Mf ∈ Zd

0×d

e f0 ∈ Z.

´

E importante notar que, em ambas as defini¸c˜oes, ´e somente permitido a Mf e f0

possu´ırem valores inteiros, n˜ao podendo ser vari´aveis, mesmo que estas se comportem

como constantes simb´olicas2.

Defini¸c˜ao 4 (La¸co com controle afim). Um la¸co ´e dito com controle afim (ACL) se,

e somente se, ele satisfaz as seguintes condi¸c˜oes:

• Ser uma estrutura perfeitamente aninhada de la¸cos;

• Possuir limites superiores e inferiores de cada la¸co como fun¸c˜oes afins envolvendo

´ındices dos la¸cos mais externos e constantes;

• Possuir corpo formado apenas por comandos que acessam escalares ou vetores, com dependˆencia e acesso afim, isto ´e, n˜ao s˜ao permitidas dependˆencias irregulares (como vetores indexando vetores, por exemplo).

Outras defini¸c˜oes importantes, antes de esclarecer o modelo matem´atico utilizado, s˜ao

mostradas a seguir.

Defini¸c˜ao 5 (Hiperplano). Um hiperplano pode ser um espa¸co vetorial, transforma¸c˜ao

afim ou subespa¸co afim de dimens˜ao dim(H) = d − 1 de um espa¸co d-dimensional. Logo,

um hiperplano pode ser representado por uma equa¸c˜ao afim. Um hiperplano divide o

espa¸co em dois semiespa¸cos.

Em especial, em um espa¸co tridimensional, um hiperplano ´e o pr´oprio plano; num

plano, um hiperplano ´e uma reta; numa reta, um ponto.

Defini¸c˜ao 6 (Semiespa¸cos). Um semiespa¸co ´e o conjunto de pontos de um espa¸co

d-dimensional que est˜ao de um lado do hiperplano. Logo, todo semiespa¸co pode ser

representado por uma inequa¸c˜ao afim. Caso algum semiespa¸co inclua o hiperplano, a este

´e dado o nome de semiespa¸co fechado (e pode ser representado por H≤ ou H≥); caso

contr´ario, denomina-se semiespa¸co aberto (indicado por H< ou H>).

Note que, na perspectiva do conjunto Z, para qualquer hiperplano H, Zn= H≤∪ H> = H≥∪ H<

2O termo constante simb´olica ´e utilizado aqui para descrever valores que podem variar, mas nunca no

espa¸co em quest˜ao; em uma analogia `a programa¸c˜ao de computadores, seriam vari´aveis que n˜ao mudam de valor no bloco de c´odigo sendo analisado.

(27)

3.1. Conceitos Alg´ebricos 14

.

Sistemas de equa¸c˜oes afins s˜ao frequentemente representadas seguindo a forma normal

M v = 0, onde M ´e uma matriz r × d, r ´e o n´umero de equa¸c˜oes do sistema e d ´e o tamanho

do vetor de vari´aveis e parˆametros v. Semelhantemente, em sistemas de inequa¸c˜oes afins,

utiliza-se a forma normal M v ≥ 0.

3.1.1

Modelo Polit´

opico

Defini¸c˜ao 7 (Pol´ıtopo). `A intersec¸c˜ao de um n´umero finito de semiespa¸cos fechados

d´a-se o nome de pol´ıtopo3. Todo pol´ıtopo pode ser representado por uma desigualdade

matricial como

P =x ∈ Rn

: Ax ≤ b, A ∈ Rm×n, b ∈ R .

Como consequˆencia imediata da defini¸c˜ao 7, pode-se representar um pol´ıtopo por um

sistema de inequa¸c˜oes afins e, a partir da´ı, construir uma matriz M sobre este sistema:

cada linha da matriz representar´a um semiespa¸co.

Em [13], Philippe Clauss prop˜oe um m´etodo para contagem de inteiros dentro de um

pol´ıtopo usando a teoria dos polinˆomios de Ehrhart. Esta teoria pode ser vista como

uma generaliza¸c˜ao dimensional da f´ormula de Pick no plano Euclidiano4. A discuss˜ao

deste m´etodo foge ao escopo deste trabalho, e recomenda-se a leitura de [13] para maiores

detalhes. Para fins desta disserta¸c˜ao, ´e interessante apenas saber que o n´umero de pontos

inteiros internos a um pol´ıtopo ´e cont´avel.

Modelo Matem´atico de um Programa Fonte

O primeiro passo para aplicar otimiza¸c˜oes utilizando o modelo polit´opico ´e transferir

informa¸c˜oes relevantes sobre o programa sendo compilado para a representa¸c˜ao de um

pol´ıtopo. Para isso, ´e importante saber o que ´e poss´ıvel representar atrav´es do modelo.

Como mencionado anteriormente, este trabalho foca em otimiza¸c˜oes sobre la¸cos. Mais

que isso, restringimos o conjunto dos la¸cos a serem otimizados aos la¸cos ACL – la¸cos com

controle e acessos `a mem´oria descritos por fun¸c˜oes afins. Para criar um pol´ıtopo que

represente um ACL5, s˜ao quatro as principais informa¸c˜oes que devem ser armazenadas,

que ser˜ao ilustradas pelo problema descrito a seguir.

3Em se tratando de espa¸cos tridimensionais, pol´ıtopos s˜ao conhecidos por poliedros. Similarmente,

para duas dimens˜oes temos os pol´ıgonos, e pol´ıcoros em quatro dimens˜oes.

4A f´ormula de Pick ´e um teorema publicado em 1899 por George Alexander Pick, e trata-se de um

m´etodo simples para calcular a ´area de pol´ıgonos.

5Dado que as fun¸oes afins extra´ıdas de la¸cos para a representa¸ao do pol´ıtopo s˜ao (para la¸cos com

(28)

3.1. Conceitos Alg´ebricos 15

Suponha um conjunto de restri¸c˜oes afins que descrevem uma parte de um espa¸co

d-dimensional. O conjunto dessas restri¸c˜oes ´e chamado dom´ınio. Considere, sem perda

de generalidade, o seguinte conjunto de restri¸c˜oes, onde i e j s˜ao as duas dimens˜oes do

espa¸co (d = 2), e m e n s˜ao os parˆametros (constantes simb´olicas):

2 ≤ i ≤ n 2 ≤ j ≤ m j ≤ n + 2 − i

(3.1)

Considere, ainda, que se conhece parcialmente os valores dos parˆametros, chamado de

contexto, expressados tamb´em como inequa¸c˜oes afins:

m ≥ 2

n ≥ 2 (3.2)

Uma representa¸c˜ao gr´afica dessa parte do espa¸co bidimensional pode ser vista na figura

3.1. j>=2 j<=m i<=n i>=2 j 1 2 1 2 n i m j<=n+2-i

Figura 3.1: Representa¸c˜ao gr´afica de espa¸co bidimensional. Os pontos na figura mostram

os valores inteiros contidos no espa¸co ilustrado.

Um algoritmo para percorrer os pontos inteiros mostrados na figura, dados o dom´ınio e o contexto, pode ser visto no algoritmo 3.2.

Algoritmo 3.2: Exemplo de passeio sobre pol´ıtopo da figura 3.1. for i ← 2 to n do

for j ← 2 to m do S(i, j)

end end

(29)

3.1. Conceitos Alg´ebricos 16

Dados o contexto e o dom´ınio como sistemas de inequa¸c˜oes afins, como visto neste

exemplo, podem-se represent´a-los atrav´es de pol´ıtopos.

Note que o corpo do la¸co no algoritmo 3.2 ´e mostrado como uma fun¸c˜ao dos ´ındices

dos la¸cos em torno do bloco. Na verdade, n˜ao ´e importante representar completamente

as senten¸cas presentes no corpo do la¸co atrav´es do modelo, mas apenas as dependˆencias

entre elas (a importˆancia das dependˆencias para a otimiza¸c˜ao ´e discutida na se¸c˜ao 3.2.1).

Para ser poss´ıvel computar as dependˆencias, ´e necess´ario possuir conhecimento sobre a

intera¸c˜ao entre as opera¸c˜oes no conjunto de ´ındices.

Em ACLs apenas s˜ao permitidos vetores com acesso descrito por fun¸c˜oes afins,

poden-do-se tamb´em representar esses acessos por pol´ıtopos; cada linha da matriz representaria

uma dimens˜ao do vetor, e cada coluna, as dimens˜oes e parˆametros do pol´ıtopo. Assim,

todo acesso a uma vari´avel pode ser modelada por uma matriz de acesso, juntamente com

um identificador para o tipo de acesso como leitura ou escrita.

Por ´ultimo, os dom´ınios somente definem um conjunto de pontos inteiros a percorrer,

mas n˜ao especificam uma ordem para fazˆe-lo. Para ser poss´ıvel expressar a ordem de

execu¸c˜ao entre as senten¸cas presentes nos la¸cos, s˜ao usadas as fun¸c˜oes de escalonamento.

Defini¸c˜ao 8 (Fun¸c˜ao de escalonamento). Um escalonamento θ de um programa

´e uma fun¸c˜ao que mapeia toda opera¸c˜ao para um vetor inteiro que representa o tempo

l´ogico. Para toda senten¸ca S, seu escalonamento θS pode ser representado por uma matriz

Θt×d, onde t ´e o n´umero de dimens˜oes de tempo, e d ´e a dimensionalidade do conjunto de

´ındices de S mais o n´umero de parˆametros simb´olicos.

Em outras palavras, um escalonamento θS pode ser utilizado para indicar uma data

l´ogica para a execu¸c˜ao de uma senten¸ca, a partir das dimens˜oes originais, dos parˆametros

e de escalares. Em [18] ´e discutido um m´etodo bastante simples para calcular as fun¸c˜oes

de escalonamento. A ideia ´e construir uma Loop Statement Tree6 (LST) para o programa,

e ler o escalonamento para cada senten¸ca. Observe o algoritmo 3.3.

A LST correspondente ´e dada na figura 3.2. Para sua constru¸c˜ao, um n´o raiz n˜ao

nomeado ´e criado, com arestas dirigindo-se aos n´os que representam todos os la¸cos mais

externos do algoritmo; no exemplo, apenas o la¸co de ´ındice i encontra-se no n´ıvel mais externo. O n´o que representa este la¸co, ent˜ao, ´e nomeado por sua vari´avel de indu¸c˜ao, e a

aresta que leva at´e ele ´e nomeada por um ´ındice inteiro que representa a ordem cronol´ogica

para sua execu¸c˜ao (a ordem em que o la¸co aparece no programa). Internos ao la¸co de

´ındice i, encontram-se um la¸co de ´ındice j, a senten¸ca S2 e outro la¸co de ´ındice tamb´em j,

nesta ordem. Para senten¸cas, um n´o com um r´otulo identificador ´e criado. Novamente, as

arestas recebem identificadores que representam sua ordem no c´odigo original. Os passos

6Uma Loop Statement Tree ´e uma representa¸ao em ´arvore da estrutura hier´arquica de la¸cos, que

(30)

3.1. Conceitos Alg´ebricos 17

Algoritmo 3.3: N´ucleo do algoritmo de fatora¸c˜ao de Cholesky.

for i ← 1 to n do for j ← 1 to i − 1 do S1: A[i][j] -= A[i][j]; end S2: A[i][i] = sqrt(A[i][i]); for j ← i + 1 to n do for k ← 1 to i − 1 do S3: A[j][i] -= A[j][k]*A[i][k]; end S4: A[j][i] /= A[i][i]; end end

descritos s˜ao repetidos para cada n´o que represente um la¸co at´e que todas as folhas na

´

arvore representem senten¸cas.

i j j k S2 S1 S4 S3 0 2 1 0 0 1 0 0

Figura 3.2: Exemplo de Loop Statement Tree para o algoritmo 3.3.

A partir dessa ´arvore, obtemos as fun¸c˜oes de escalonamento

         θS1(i, j) T = (0, i, 0, j, 0)T θS2(i) T = (0, i, 1)T θS3(i, j, k) T = (0, i, 2, j, 0, k, 0)T θS4(i, j) T = (0, i, 2, j, 1)T

onde θT ´e a matriz transposta de θ. Para entender sua constru¸c˜ao, ´e necess´aria a seguinte

defini¸c˜ao:

Defini¸c˜ao 9 (Passeios em ´arvores). Dada uma ´arvore T, um passeio ´e qualquer

(31)

3.1. Conceitos Alg´ebricos 18

v´ertices s˜ao adjacentes se, e s´o se, s˜ao v´ertices consecutivos nesta lista, e mediados pela

aresta que os liga. Para o caso espec´ıfico de ´arvores, todo passeio ´e tamb´em chamado de

caminho (passeio que n˜ao repete v´ertices), uma vez que ´arvores n˜ao possuem ciclos.

Assim sendo, para construir a fun¸c˜ao de escalonamento para S1, por exemplo,

realiza-se o pasrealiza-seio da raiz at´e a folha que representa esta senten¸ca na LST. O escalonamento

para a dada senten¸ca, denotado por θS1, ´e a lista obtida para tal passeio, que (note) ´e

dada em fun¸c˜ao dos n´os i e j. De maneira semelhante, podem-se descrever as fun¸c˜oes de

escalonamento para todas as demais senten¸cas pertencentes a esta ´arvore.

Por constru¸c˜ao, perceba que nenhum v´ertice de uma LST possui mais que um caminho

at´e a raiz: primeiro porque, por defini¸c˜ao, n˜ao existem ciclos em ´arvores; segundo,

ne-nhuma senten¸ca (v´ertices mais externos da ´arvore, ou simplesmente folhas) aparece mais

de uma vez na ´arvore. Ent˜ao, a fun¸c˜ao de escalonamento de um v´ertice que representa

uma senten¸ca S ´e dada pelo caminho da raiz da LST at´e a folha que representa a dada

senten¸ca.

Essas fun¸c˜oes de escalonamento dependem das vari´aveis de indu¸c˜ao, e d˜ao, para cada

senten¸ca, uma data de execu¸c˜ao ´unica. Gra¸cas a isso, ´e poss´ıvel gerar c´odigo equivalente

ao original a partir de uma representa¸c˜ao de pol´ıtopo.

Al´em disso, as fun¸c˜oes de escalonamento s˜ao fundamentais para a reestrutura¸c˜ao de

c´odigo. ´E atrav´es delas que otimiza¸c˜oes ou a pr´opria paraleliza¸c˜ao do c´odigo s˜ao

im-plementadas: s˜ao essas fun¸c˜oes que ditam a ordem a seguir para percorrer o conjunto

de ´ındices. Mas ´e importante perceber que nem todo escalonamento para um conjunto

de ´ındices ´e v´alido: somente os escalonamentos que respeitam as dependˆencias entre as

senten¸cas pertencentes ao la¸co. Formalmente, ´e necess´ario ao escalonamento respeitar `a

seguinte condi¸c˜ao de casualidade:

Defini¸c˜ao 10 (Condi¸c˜ao de casualidade). Um escalonamento deve obedecer ao

se-guinte princ´ıpio de casualidade, que estabelece uma rela¸c˜ao entre dependˆencias e

escalo-namentos:

(∀u, v ∈ Ω : u δ v ⇒ θ(u) + 1 ≤ θ(v)).

Onde Ω ´e o conjunto de todas as opera¸c˜oes7 de uma senten¸ca, e u δ v representa

uma dependˆencia de v para com u8. Em outras palavras, se alguma instˆancia de uma

senten¸ca depende de uma instˆancia de outra senten¸ca, o escalonamento da segunda deve

ser anterior ao da primeira para preservar o sentido desta dependˆencia.

7Uma opera¸ao pode ser vista como uma instˆancia em tempo de execu¸ao de uma senten¸ca. 8Cf. defini¸ao 11.

(32)

3.2. Alcan¸cando o Paralelismo 19

3.2

Alcan¸

cando o Paralelismo

´

E trabalho do compilador transformar uma computa¸c˜ao de uma representa¸c˜ao em alto

n´ıvel, que ´e f´acil para um humano entender, para uma representa¸c˜ao em baixo n´ıvel, que

a m´aquina pode executar. Um ponto cr´ıtico ´e que a representa¸c˜ao humana raramente

comporta detalhes sobre a arquitetura da m´aquina que executar´a o programa, for¸cando

a introdu¸c˜ao de trechos ineficientes de c´odigo em linguagens de alto-n´ıvel. A fim de

eliminar essa ineficiˆencia do c´odigo, fases de otimiza¸c˜ao do c´odigo foram introduzidas aos

compiladores.

Otimiza¸c˜oes tˆem sido desenvolvidas para alcan¸car o m´aximo desempenho, apesar das

diferen¸cas nas arquiteturas dos computadores – entre escalares, superescalares, vetoriais,

etc. Como consequˆencia natural, compiladores tamb´em deveriam ser respons´aveis por

transformar o c´odigo automaticamente para que o programa resultante tenha vantagens

sobre m´aquinas paralelas; afinal, o compilador ´e livre para transformar o c´odigo, desde

que o programa gerado compute os mesmos resultados que o original.

Mas as otimiza¸c˜oes – e, na maioria das vezes, a combina¸c˜ao delas – que permitem

explorar o paralelismo s˜ao demasiado radicais. Por exemplo, para alcan¸car desempenho

´

otimo num algoritmo de multiplica¸c˜ao de matrizes, ´e necess´ario realizar loop interchange,

loop splitting, loop distribution, vetoriza¸c˜ao e, enfim, paraleliza¸c˜ao [29]. Metade dessas

transforma¸c˜oes nem ao menos s˜ao encontradas na maioria dos compiladores.

Como visto na se¸c˜ao anterior, as transforma¸c˜oes (e, em especial, as que exploram

paralelismo) modificam a ordem de execu¸c˜ao das instru¸c˜oes do programa. O principal

desafio que um compilador deve enfrentar ´e justamente determinar quando dada ordem de

execu¸c˜ao ´e v´alida. Em outras palavras, o compilador deve conhecer, e respeitar, restri¸c˜oes

que garantam que o c´odigo sempre ir´a computar os mesmos resultados do c´odigo original.

Dado que tais restri¸c˜oes limitam as transforma¸c˜oes, a chave ´e encontrar um conjunto

m´ınimo de restri¸c˜oes que garantam que o c´odigo transformado ir´a gerar o resultado correto.

Nesta disserta¸c˜ao, usaremos um conjunto de restri¸c˜oes denominadas dependˆencias.

Defini¸c˜ao 11 (Dependˆencia). Dependˆencia pode ser vista como uma rela¸c˜ao entre as

instru¸c˜oes de um programa. O par hS1, S2i ´e uma rela¸c˜ao de dependˆencia se S1 deve

executar antes de S2 em qualquer reordenamento v´alido das instru¸c˜oes. Comumente,

denota-se por S1 δ S2, para duas senten¸cas S1 e S2no c´odigo, representando a dependˆencia

de S2 para com S1.

Para ilustrar esta defini¸c˜ao, considere o fragmento de c´odigo a seguir.

Para este c´odigo, os resultados originais est˜ao definidos como aqueles gerados quando

(33)

3.2. Alcan¸cando o Paralelismo 20

Algoritmo 3.4: Trecho de c´odigo que ilustra dependˆencias de dados e rela¸c˜oes de

ordem entre essas dependˆencias.

S1: pi ← 3.14159

S2: r ← 5

S3: area ← pi ∗ r2

hS2,S1,S3i produz o mesmo resultado (o mesmo valor de ´area ´e calculado). As

de-pendˆencias presentes em S3 para as duas instru¸c˜oes anteriores, por´em, impedem que

esta seja executada em qualquer outro momento.

Apesar de ser um conceito f´acil de identificar em trechos mais simples (sem desvios),

a otimiza¸c˜ao de tais trechos n˜ao garante a utiliza¸c˜ao efetiva dos recursos em m´aquinas

paralelas: o conceito de dependˆencia deve ser aplicado a fragmentos mais complexos,

como corpos de la¸co, ou chamadas a fun¸c˜oes, por exemplo. Nesses ambientes, entretanto,

podem ocorrer rela¸c˜oes de dependˆencia muito mais dif´ıceis de serem manipuladas. Um

exemplo est´a mostrado no fragmento de c´odigo exibido no algoritmo 3.5.

Algoritmo 3.5: Trecho de c´odigo que ilustra dependˆencia c´ıclica de dados.

for i ← 1 to N do

S1: A[i] ← B[i] + 1

S2: B[i + 1] ← A[i] − 5

end

Neste algoritmo, existe uma dependˆencia que for¸ca a ordem hS1,S2i, porque todo

elemento de A computado pela primeira senten¸ca ´e imediatamente utilizado pela segunda

senten¸ca, e tamb´em existe uma outra rela¸c˜ao do tipo hS2,S1i, uma vez que toda itera¸c˜ao

do la¸co usa o valor do elemento em B calculado na itera¸c˜ao anterior. A este tipo de

dependˆencia, d´a-se o nome de dependˆencia c´ıclica. ´E importante notar que dependˆencias

c´ıclicas tamb´em podem ocorrer numa instru¸c˜ao sobre ela mesma, como ser´a discutido no

algoritmo 3.7.

3.2.1

An´

alise das Dependˆ

encias

Otimiza¸c˜oes de c´odigo, em especial as mais sofisticadas, introduzem alguma complexidade

ao processo de compila¸c˜ao; a paraleliza¸c˜ao autom´atica introduz muito mais complexidade

a este processo. Para computadores paralelos, encontrar paralelismo em c´odigo sequencial

´e, por si s´o, uma otimiza¸c˜ao. Para auxiliar nessa tarefa, as dependˆencias no c´odigo do

programa s˜ao identificadas e as otimiza¸c˜oes s˜ao ajustadas para preservar o sentido dessas

(34)

3.2. Alcan¸cando o Paralelismo 21

Defini¸c˜ao 12 (Teorema Fundamental de Dependˆencia). Qualquer transforma¸c˜ao

que reordena senten¸cas preservando toda dependˆencia no programa preserva tamb´em o

significado do programa.

A prova do teorema acima pode ser visto em [29]. Como consequˆencia direta deste

teo-rema, qualquer transforma¸c˜ao que busque paralelismo por reescalonamento de instru¸c˜oes ´e

v´alida, desde que preserve o sentido das dependˆencias. Ao usar as dependˆencias do c´odigo

como base para transforma¸c˜oes, ent˜ao, sua identifica¸c˜ao e an´alise s˜ao pontos cr´ıticos:

de-vem prover informa¸c˜oes suficientes para descobrir se (e como) alguma transforma¸c˜ao pode

ser aplicada.

Dependˆencias representam dois diferentes tipos de restri¸c˜oes para transforma¸c˜oes no

c´odigo: restri¸c˜oes que permitem ou n˜ao que instru¸c˜oes executem baseadas na execu¸c˜ao de

outras instru¸c˜oes, conhecidas por dependˆencias de controle; e restri¸c˜oes que garantem que

dados sejam consumidos e produzidos em determinada ordem, chamadas de dependˆencias

de dados. Este trabalho concentra-se apenas no ´ultimo tipo de dependˆencias, visto que, no

caso geral, paralelismo ´e encontrado ao aplicar decomposi¸c˜ao de dados9. As dependˆencias

de controle, portanto, ser˜ao mantidas pelas vers˜oes das transforma¸c˜oes discutidas aqui10.

Formalmente,

Defini¸c˜ao 13 (Dependˆencia de dados). Existe dependˆencia de dados da senten¸ca S1

para S2 (ou seja, a senten¸ca S2 depende de S1) se, e somente se, (1) ambas as senten¸cas

acessam a mesma posi¸c˜ao de mem´oria e, no m´ınimo, uma delas realiza uma escrita e (2)

h´a um caminho poss´ıvel entre S1 e S2 durante a execu¸c˜ao.

Note que instru¸c˜oes que realizam leitura de mesmos dados n˜ao caracterizam

de-pendˆencia de dados: uma vez que a leitura n˜ao modifica dados na mem´oria, a ordem

entre duas ou mais leituras pode ser alterada sem modificar a semˆantica do programa.

Logo, pode existir uma dependˆencia de dados entre duas instru¸c˜oes, sejam S1, S2 e S1 δ

S2, se S1 escreve em um dado que S2 ler´a (chamada dependˆencia verdadeira), se S1 lˆe

de um dado que ser´a atualizado por S2 (antidependˆencia), ou se S1 escreve num dado

que ser´a sobrescrito por S2 (dependˆencia de sa´ıda). Ademais, duas instru¸c˜oes que n˜ao

9ecnica na qual v´arias tarefas paralelas executam opera¸oes similares sobre conjuntos diferentes de

dados.

10Com algumas modifica¸oes, as transforma¸oes podem passar a manipular certos tipos de dependˆencias

de controle. Al´em disso, algumas dessas dependˆencias podem ser traduzidas em dependˆencias de dados, o que permitiria o uso das transforma¸c˜oes como s˜ao mostradas aqui; mas essas modifica¸c˜oes n˜ao ser˜ao discutidas neste trabalho. Dessa forma, qualquer cita¸c˜ao a dependˆencias no texto a partir daqui, faz referˆencia `a dependˆencia de dado (exceto quando explicitado). Para maiores detalhes sobre tratamento de dependˆencias de controle, consultar o cap´ıtulo 7 da referˆencia [29].

Referências

Documentos relacionados

Sujeitos que já possuíssem amplo conhecimento referente à modelagem utilizando as ferramentas ArgoUml ou Gliffy, poderiam concluir os diagramas em menos tempo, com

Este ano, esperamos mais saúde para todos, mais trabalho e por consequência, mais dinheiro no bolso de cada um de nossos associados.. Que possamos continuar superando

ton, por meio das transforma¸c˜ oes de Galileo e, no caso da Relatividade Especial de Einstein, por meio das transforma¸c˜ oes de Lorentz, como veremos mais adiante.. De maneira

Ficam estipuladas as multas contratuais previstas nesta Convenção Coletiva de Trabalho, a serem aplicadas aos infratores desta normativa, assim discriminadas:.. a) a infração

Devo dizer que desde a última reunião de Toronto apresentamos o projeto base para a apresentação de políticas precoce, para que possam fazer comentários dentro do processo de PDP

alanı ile bağlantısı direkt olarak kurulabilecek ilk madde ve malzemeler’ şeklinde tanımlanan ilk madde ve malzeme giderlerine ilişkin bu açıklamadan çıkarılan anlam;

O presente artigo pretende aprofundar uma discus- são já avançada nos estudos sobre a produção imobiliária em cidades médias desenvolvidos no âmbito do Grupo de Pesquisa

Perigo por aspiração Com base nos dados disponíveis, os critérios de classificação não foram atendidos.. Outras informações Não há dados de toxicidade completos para