Você está na página 1de 26

Pontifícia Universidade Católica do Rio Grande do Sul

Faculdade de Informática
Pós-Graduação em Ciência da Computação

Computação verificada de alto desempenho aplicada à


resolução de sistemas lineares intervalares densos de grande
porte em arquiteturas de memória compartilhada

Cleber Roberto Milani

Orientador: Prof. Dr. Luiz Gustavo Leão Fernandes

Plano de Estudo e Pesquisa

Porto Alegre, dezembro de 2008


Sumário

LISTA DE TABELAS 2

LISTA DE FIGURAS 3

LISTA DE SÍMBOLOS E ABREVIATURAS 4

Capítulo 1: Introdução 5
1.1 Trabalhos Relacionados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

Capítulo 2: Computação verificada e sua aplicação na resolução de SELAs 8


2.1 Aritmética Intervalar e Arredondamentos . . . . . . . . . . . . . . . . . . . . . . . 8
2.2 Computação verificada e resolução de SELAs . . . . . . . . . . . . . . . . . . . . . 10
2.2.1 Método Baseado em no Método de Newton . . . . . . . . . . . . . . . . . . 11

Capítulo 3: Arquiteturas de memória compartilhada 12


3.1 Classificação das arquiteturas de computador . . . . . . . . . . . . . . . . . . . . . 12
3.2 Programação em arquiteturas paralelas . . . . . . . . . . . . . . . . . . . . . . . . . 13

Capítulo 4: Programação numérica de alto desempenho 16


4.1 Basic Linear Algebra Subprograms - BLAS . . . . . . . . . . . . . . . . . . . . . . 16
4.2 LINPACK, LAPACK e ScaLAPACK . . . . . . . . . . . . . . . . . . . . . . . . . . 17

Capítulo 5: Proposta para a Dissertação de Mestrado 19


5.1 Motivação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
5.2 Objetivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
5.3 Metodologia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
5.4 Cronograma de atividades . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

1
Lista de Tabelas

5.1 Cronograma das atividades a serem desenvolvidas no ano de 2009. . . . . . . . . . 22

2
Lista de Figuras

3.1 Classificação das arquiteturas paralelas segundo critérios relativos à memória [12]. 13

3
Lista de Símbolos e Abreviaturas

ED Equação Diferencial 5
SELA Sistema de Equações Lineares Algébricas 5
C-XSC C for eXtended Scientific Computing 6
LAPACK Linear Algebra PACKage 6
ScaLAPACK SCAlable Linear Algebra PACKage 6
MPI Message Passing Interface 7
NUMA Non-Uniform Memory Access 7
MIMD Multiple Instruction Streams Multiple Data Streams 12
UMA Uniform Memory Access 12
NUMA Non-Uniform Memory Access 12
NCC-NUMA Non-Cache-Coherent Non-Uniform Memory Access 13
CC-NUMA Cache-Coherent Non-Uniform Memory Access 13
SC-NUMA Software-Coherent Non-Uniform Memory Access 13
COMA Cache Only Memory Architeture 13
Pthreads POSIX Threads 14
OpenMP Open Multi-Processing 14
SO Sistema Operacional 14
BLAS Basic Linear Algebra Subprograms 16
ATLAS Automatically Tuned Linear Algebra Software 17
TLB Translation Look-aside Buffer 17
PBLAS Parallel Basic Linear Algebra Subprograms 17
BLACS Basic Linear Algebra Communication Subprograms 17
SPMD Single-Program-Multiple-Data 17
PLASMA Parallel Linear Algebra for Scalable Multi-Core Architectures 20

4
1 Introdução

Diversos problemas e situações das mais variadas áreas do conhecimento podem ser modelados
através de Equações Diferenciais (EDs) e Sistemas de Equações Lineares Algébricas (SELAs). Uma
ED é definida em um conjunto infinito de pontos, ou seja, em um espaço contínuo. Porém, para que
possa ser resolvida computacionalmente, faz-se necessário discretizá-la (criar um espaço discreto e
finito), processo esse que implica na resolução de SELAs. Um sistema linear é tipicamente expresso
na forma A~x = ~b, onde A é uma matriz formada pelos coeficientes, ~x é o vetor das incógnitas do
sistema, as quais deverão ser encontradas, e ~b é o vetor dos termos independentes. O sistema é
composto por n equações com n incógnitas e, quando empregado na modelagem de problemas ou
discretização de EDs, o n costuma ser na ordem dos milhares. SELAs cujo valor de n é maior do
que 50 são ditos de grande porte e podem ser densos ou esparsos. Um sitema esparso é aquele
em que 80% ou mais dos coeficientes das incógnitas nas equações são nulos, enquanto os densos
possuem coeficientes não nulos para mais de 20% das variáveis [8, 7, 6].
Naturalmente, a resolução de SELAs densos de grande porte só é viável utilizando-se ferra-
mentas computacionais e, dependendo do tamanho do problema, ferramentas para computação
paralela de alto desempenho. Em Ciência da Computação, no entanto, a garantia de que um
algoritmo foi testado e está correto não necessariamente implica que o resultado computado por
ele será correto [15]. Freqüentemente um computador digital produz resultados incorretos para
um problema matemático, não devido a erros de programação ou ao uso de hardware não confiá-
vel, mas, simplesmente, porque computadores são máquinas discretas e finitas que não conseguem
tratar alguns dos aspectos contínuos e infinitos da matemática. Até mesmo um número simples
1
como 10 pode ser um grande causador de problemas, pois um computador não consegue executar
1
cálculos com o mesmo. Isso ocorre porque a fração decimal 10 não possui representação finita
exata na notação binária, logo, o computador precisa aproximá-la [16].
Nesse contexto, a verificação automática dos resultados é uma ferramenta importante para
reduzir o impacto dos erros de aritmética na computação numérica. Os computadores digitais
possuem dois sistemas numéricos em seu hardware: sistema de inteiros e sistema de ponto flutuante.
A aritmética de inteiros opera sem erros dentro uma faixa limitada, pois, estando a operação nessa
faixa, basta que computador utilize o número necessário de dígitos para representá-la de maneira
exata. Por outro lado, na aritmética de ponto flutuante não existe tal garantia, pois as operações
aproximam, utilizando frações finitas, números reais oriundos dos problemas numéricos, os quais
são originalmente expressos por frações infinitas [15].
Uma operação em ponto flutuante é dita de máxima exatidão quando o resultado arredondado
difere do resultado exato em no máximo uma unidade na última casa decimal. Essa diferença
entre o resultado exato e o arredondado é dita erro de arredondamento [16]. A máxima exatidão
acontece na maioria dos computadores quando considerando operações de ponto flutuante indivi-
duais, porém, após algumas operações consecutivas, o resultado pode ser completamente errado.
Diversas são as razões para isso, um exemplo típico é a soma de dois números de diferentes ordens
de magnitude que não pode ser processada corretamente no sistema de ponto flutuante. Uma
vez que os computadores atuais executam milhões de operações em ponto flutuante por segundo,
atenção especial deve ser dada à confiabilidade dos resultados. Na aritmética de ponto flutuante
a maioria dos erros ocorre nas acumulações, ou seja, na execução de uma seqüência de somas e
subtrações. Por outro lado, a multiplicação e a divisão são operações relativamente estáveis em
ponto flutuante. Já na aritmética de ponto fixo, a acumulação é realizada sem erros, desde que a

5
1. Introdução 6

unidade aritmética do computador ofereça um registrador capaz de cubrir toda a faixa do sistema
de ponto flutuante. Além disso, se tal registrador não estiver disponível em hardware, o mesmo
pode ser simulado em software [15].
Nos últimos anos, diversas técnicas de análise numérica têm sido desenvolvidas visando pos-
sibilitar que o computador verifique por si só a corretude do resultado computado. Uma grande
vantagem da verificação automática é que o computador pode determinar rapidamente quando
o resultado encontrado não é correto e/ou útil e, nesse caso, escolher um algoritmo alternativo
ou repetir a computação utilizando maior precisão. Adicionalmente, muitas vezes tais técnicas
permitem ao computador estabelecer a existência e unicidade da solução. Uma dessas técnicas
é o produto escalar ótimo, o qual utiliza o registrador de ponto fixo e possibilita representar de
maneira exata bem como realizar todas as operações entre números de ponto flutuante e opera-
ções entre vetores e matrizes com máxima exatidão. Nesse caso apenas um arredondamento é
necessário no momento de converter o resultado final para o ponto flutuante [15, 34]. Em [24]
discute-se a implementação de algoritmos de ponto flutuante utilizando-se ponto fixo. A biblioteca
C-XSC (C for eXtended Scientific Computing) [18], amplamente utilizada no desenvolvimento de
algoritmos numéricos de máxima exatidão e com verificação automática de resultados, calcula o
produto escalar em uma implementação via software do registrador.
Entretanto, quando implementado em hardware, o produto escalar ótimo é mais rápido até
mesmo do que a computação do produto escalar em aritmética de ponto flutuante tradicional,
uma vez que essa é feita em um laço de repetição [34]. Adicionalmente, Kulisch [23] mostrou
que acumular produtos em ponto fixo é a forma mais rápida de acumular produtos escalares em
todos os tipos de computadores e que a instrução que calcula o produto escalar em hardware pode
ser implementada com pequeno custo de hardware. Dessa forma, aumenta-se ao mesmo tempo
a velocidade da computação e a exatidão do resultado computado. Porém, visando adaptar o
computador para o controle automático do erro, além de basear sua aritmética no produto escalar
ótimo, outra técnica faz-se necessária: todas as operações com números de ponto flutuante devem
ser feitas com arredondamentos diretos. Com isso torna-se possível construir uma aritmética
intervalar no computador, levando, assim, o contínuo para o mesmo. O cálculo exato do produto
escalar entre vetores de ponto flutuante de qualquer dimensão finita e a possibilidade de trabalhar
com o contínuo abrem novos horizontes na análise numérica [15].
A aritmética intervalar é a ferramenta matemática básica em computação numérica verificada.
Não é uma idéia nova, sua primeira aparição foi registrada em 1924 e foi reinventada diversas vezes
desde então, nunca foi o foco principal da computação numérica, mas também nunca foi total-
mente abandonada[16, 17]. A computação verificada garante o rigor matemático dos resultados da
computação fornecendo um resultado intervalar, ou seja, traz como resultado da computação um
intervalo, o qual com certeza contém o resultado exato. Tal intervalo recebe o nome de enclosure,
ou, aproximação [21].
A utilização da computação verificada nos problemas inicialmente citados, ou seja, naqueles
que exigem a resolução de SELAs, implicaria, em princípio, na necessidade de resolver um número
infinito de matrizes contidas em um intervalo. Entretanto, como esse é um problema NP-Completo,
o que acontece na prática é a computação de um intervalo estreito o qual contém tais matrizes.
Em geral, soluções aproximadas de sistemas lineares pontuais, ou seja, aqueles cujas equações são
formadas por números pontuais, são obtidas com o auxílio de bibliotecas matemáticas otimizadas,
como LINPACK [10], LAPACK (Linear Algebra PACKage) [9, 1] ou ScaLAPACK (SCAlable
Linear Algebra PACKage) [4] e são então utilizadas na obtenção de limites para formar intervalos
onde a solução reside [17]. Entretanto, mesmo com a utilização dessas bibliotecas de software
otimizadas, a resolução do sistema continua apresentando grande custo computacional quando
se tratando de sistemas densos de grande porte. Esse custo torna-se ainda maior ao considerar
sistemas lineares intervalares densos de grande porte, ou seja, aqueles em que as matrizes contêm
intervalos como coeficientes das incógnitas, ao invés de valores pontuais. Em geral, tais sistemas
são utilizados na representação de dados incertos, ou seja, aqueles em que a modelagem não é
exata ou em que os instrumentos empregados para obtenção dos dados apresentam variações,
dentre outros. Nesses casos, para tornar viável a resolução do sistema em um tempo aceitável,
faz-se necessária a aplicação de computação paralela de alto desempenho [21].
1. Introdução 7

Diversos trabalhos de computação verificada têm sido realizados utilizando técnicas de compu-
tação paralela para agregados de computadores (clusters). Tais trabalhos combinam a biblioteca
MPI (Message Passing Interface) [31] com as bibliotecas matemáticas previamente citadas para
resolução de sistemas lineares. Alguns deles, como [20] e [22], trabalham com sistemas lineares
do tipo pontual, em outros casos, como [21], são resolvidos sistemas lineares intervalares. Entre-
tanto, nos últimos anos muitas modificações vêm ocorrendo na computação de alto desempenho.
Considerando-se que, em poucos anos, o número de núcleos de processamento em processadores
multi-core deve exceder uma dezena e que tais processadores vêm ganhando cada vez mais espaço
no mercado, implementações eficientes das aplicações numéricas para essas arquiteturas tornam-se
uma necessidade premente. No contexto atual, atencão especial é devida também às máquinas
NUMA (Non-Uniform Memory Access), pois tais arquiteturas têm tido participação crescente em
centros de pesquisa e universidades, os quais encontram-se, também, dentre os principais usuários
que precisam trabalhar com a resolução de SELAs como os acima descritos porém não possuem
acesso a grandes agregados de computadores como os grandes centros de computação.
Tanto os processadores multi-core como as arquiteturas NUMA são máquinas que possuem
memória compartilhada, ou seja, compartilham um mesmo espaço de endereçamento. Em má-
quinas desse tipo o paradigma de troca de mensagens introduz custos adicionais e operações de
cópia/escrita na memória desnecessárias, o que diminui o desempenho e torna mais difícil o es-
calonamento de atividades que podem ser executadas em paralelo [2]. Logo, o desenvolvimento
de ferramentas para resolução de SELAs com computação verificada de alto desempenho que
explorem adequadamente máquinas de memória compartilhada é um nicho em ascenção e cuja
exploração pode oferecer resultados bastante interessantes, uma vez que permitirá a universali-
zação do uso das ferramentas para resolução de grandes problemas de otimização e modelagem
das mais diversas áreas do conhecimento. Nesse contexto, a presente proposta pode ser resumida
em desenvolver um solver (ferramenta computacional para resolução) de SELAs den-
sos intervalares de grande porte com verificação automática dos resultados otimizado
para execução em arquiteturas de memória compartilhada.
O restante desta proposta está organizada da seguinte forma: o próximo capítulo apresenta
os conceitos básicos da computação verificada e sua aplicação na resolução de sistemas lineares.
O Capítulo 3 discute brevemente as características das arquiteturas de memória compartilhada
e características para programação de tais arquiteturas. No Capítulo 4 discute-se rapidamente
algumas das bibliotecas mais utilizadas mundialmente para desenvolvimento de software em com-
putação numérica e álgebra linear de alto desempenho. Por fim, o Capítulo 5 detalha a proposta de
Dissertação de Mestrado, definindo as atividades a serem desenvolvidas bem como o cronograma
para execução das mesmas.

1.1 Trabalhos Relacionados


Existem, atualmente, diversos trabalhos sendo realizados em computação verificada que visam
sua aplicação na resolução de SELAs. Entretanto, tais trabalhos são voltados para agregados de
computadores. Duas ferramentas estado da arte são apresentados em [21] e em [34]. Maiores
detalhes sobre essas podem ser obtidos nos respectivos artigos e em [25].
O trabalho desenvolvido em [34] apresenta uma nova abordagem para o cálculo do produto
escalar, a qual em alguns casos atinge melhores resultados do que o produto escalar ótimo anterior-
mente citado. Os autores apresentam também uma versão paralela da ferramenta para agregados
de computadores. É um solver voltado a sistemas lineares intervalares densos de grande porte.
Já o trabalho desenvolvido em [21] apresenta também uma ferramenta para sistemas lineares
intervalares densos de grande porte. Utiliza para tal a aritmética interavalar do tipo ponto-médio
e raio, apresentada no próximo capítulo, e um algoritmo baseado no Método de Newton, o qual
será visto na Seção 2.2. Assim como em [34], a versão paralela da ferramenta utiliza PBLAS e
ScaLAPACK para implementação em ambientes heterogêneos com troca de mensagens.
2 Computação verificada e sua aplicação
na resolução de SELAs

A computação verificada garante o rigor matemático de um resultado fornecendo como resposta


um intervalo, o qual é chamado enclosure e contém, com certeza, o resultado exato [21]. Os mé-
todos que realizam a verificação automática dos resultados são chamados métodos auto-validados
e apresentam, basicamente, três objetivos: produzir resultados rigorosos; resolver o problema sem
que o custo computacional seja demasiadamente maior do que o dos métodos puramente numéri-
cos; incluir na computação provas da existência da solução e, quando for o caso, prova da unicidade
da mesma [30]. A verificação automática dos resultados baseia-se em dois requisitos principais:
utilização de algoritmos corretos e aplicação da teoria de aritmética intervalar em conjunto com
arredondamentos diretos. Uma das principais funções da aritmética intervalar é controlar o erro,
e, embora não elimine os efeitos dos erros de arredondamento, quando utilizada em conjunto
com arredondamentos diretos limita os mesmos [16, 17, 28]. Este capítulo apresenta a aritmética
intervalar e, na seqüência, a computação verificada e sua aplicação na resolução de SELAs.

2.1 Aritmética Intervalar e Arredondamentos


Aritmética intervalar é uma aritmética definida em um conjunto de intervalos, ao invés de números
reais. O resultado de uma computação típica, ou seja, não intervalar, é um número que representa
um ponto no eixo dos números reais e que está a alguma distância desconhecida da resposta
exata. Já em uma computação intervalar, o resultado é um par de números os quais representam
o intervalo que contém o resultado exato. Dessa forma, mesmo que a resposta exata continue
desconhecida, ao menos é possível estimar o quão desconhecida ela é [16, 21]. A avaliação intervalar
de uma expressão aritmética costuma apresentar o dobro do custo computacional que a avaliação da
mesma expressão na aritmética de ponto flutuante convencional. Entretanto, uma única avaliação
intervalar produz uma garantia do resultado que não é produzida mesmo com milhões de avaliações
convencionais. Isso porque é impossível avaliar todos os pontos no eixo dos números reais, dado
que entre dois números reais sempre existem infinitos outros números, e, além disso, muitos pontos
não são finitamente representáveis. Por outro lado, a aplicação da aritmética intervalar pura pode
conduzir a resultados que, embora sejam confiáveis, são tão genéricos, ou seja, os intervalos são
tão amplos, que acabam por ser inúteis. Assim, o ideal é executar a computação utilizando alta
exatidão e então validá-la com aritmética intervalar para, no final, obter um resultado validado
e útil. Cabe observar que a computação verificada não elimina a necessidade de verificação dos
algoritmos, compiladores, sistemas operacionais, dentre outros, uma vez que o passo de verificação
pode resultar em falsos positivos devido a erros de programação [15].
Um intervalo real é um subconjunto fechado, limitado e não vazio dos números reais represen-
tado conforme a Equação 2.1, onde x e x denotam, respectivamente, o limite inferior e superior
do intervalo [x]. Esses limites são também chamados de ínfimo e supremo, respectivamente e, por
essa razão, essa forma de representar o intervalo é chamada de representação ínfimo-supremo ou
infimum-supremum. Um intervalo real cobre toda a faixa de valores reais entre os dois limites e
nos casos em que x = x o intervalo é chamado intervalo pontual, podendo ser escrito apenas como
x ao invés de [x]. De maneira análoga, números exatos podem também ser representados como

8
2. Computação verificada e sua aplicação na resolução de SELAs 9

intervalos pontuais. Por exemplo, o número 2 pode ser escrito na forma [2, 2] [15, 16]. A Equação
2.2 apresenta outra representação possível para intervalos, a qual é chamada de representação por
ponto médio e raio, ou, midpoint-radius representation [29].

[x] := [x, x] := {x ∈ ℜ/x ≤ x ≤ x} , (2.1)

ha, αi := {x ∈ ℜ/ |x − a| ≤ α} f or a ∈ ℜ, 0 ≤ α ∈ ℜ (2.2)
As representações em (2.1) e (2.2) são equivalentes para operações teóricas em ℜ, onde não
há necessidade de arredondamento dos resultados. Entretanto, a situação muda ao considerar
cálculos executados em um computador digital, pois, nesse caso, os números reais precisam ser
aproximados por números de ponto flutuante do sistema de ponto flutuante [29]. Essa aproxi-
mação é feita por um mapeamento especial chamado arredondamento (rouding) : ℜ → F.
Além dos arredondamentos executados nos resultados de cada operação para representá-los em
ponto flutuante, arredondamentos adicionais são necessários nos dados de entrada e constantes.
Isso porque, as pessoas costumam pensar e trabalhar com notação decimal, logo, os programas
utilizam essa mesma notação em suas interfaces, o que cria a necessidade de mapear os dados
decimais fornecidos pelo usuário para o sistema de ponto flutuante binário do computador. Tais
arredondamentos costumam ocorrer em tempo de execução e, como em geral os números decimais
não possuem representação binária exata, um pequeno erro é gerado a cada mapeamento, o qual
é chamado erro de conversão.
O operação de arredondamento deve satisfazer duas condições [15]:

x = x para todo x ∈ ℜ, e
(2.3)
x ≤ y ⇒ x ≤ y para todo x, y ∈ ℜ
A primeira garante que os números não são alterados por um arredondamento. Já a se-
gunda significa que o arredondamento é monotônico, ou seja, a ordem dos elementos é mantida ao
arrendondá-los. Existem três tipos de arrendodamentos:

⊓ : Arredondamento para o elemento mais próximo do sistema


∇ : Arredondamento tendendo a −∞ ou direto para baixo (2.4)
∆ : Arredondamento tendendo a +∞ ou direto para cima
De modo a preserver a garantia de que o valor correto sempre encontra-se no intervalo, os pontos
finais de um intervalo devem ser arredondados ‘para fora’, ou seja, x é arredondado diretamente
para baixo e x é arredondado diretamente para cima [16]. Diz-se que um arredondamento é
anti-simétrico quando possui a seguinte propriedade:

(−x) = − x para todo x ∈ ℜ (2.5)


Assim, o arredondamento para o elemento mais próximo é anti-simétrico, porém os arredon-
damentos diretos ∇ e ∆ não o são. Ao invés disso, ∇ (−x) = −∆x e ∆ (−x) = −∇x. Os arredon-
damentos diretos satisfazem as condições adicionais ∇x ≤ x, e x ≤ ∆x para todo x ∈ ℜ [15].
Nesse contexto, cada uma das representações da aritmética intervalar possui algumas vanta-
gens e desvantagens. Por exemplo, a definição padrão da aritmética de ponto médio e raio costuma
resultar em intervalos mais amplos do que o desejado, efeito esse que recebe o nome de overes-
timation. É também importante considerar, quando trabalhando no sistema de ponto flutuante,
como as operações básicas ◦ ∈ {+, −, ., /} da aritmética são implementadas. No caso da represen-
tação ínfimo-supremo deve-se ter cuidado em alguns casos, especialmente nas multiplicações, pois,
dependendo do sinal dos operandos, diferentes casos da operação são utilizados. Já no caso da
aritmética representada por ponto médio e raio isso não acontece, todas as operações são definidas
diretamente sem necessidade de distinção.
As características particulares à cada aritmética não serão abordadas nesta proposta, porém
estão disponíveis para consulta em [25]. Cabe observar que a presente proposta baseia-se na utili-
zação da representação por ponto médio e raio, escolha essa determinada pelo estudo apresentado
2. Computação verificada e sua aplicação na resolução de SELAs 10

em [25] e, principalmente, devido aos resultados motivadores obtidos por [21]. Em [16] são
apresentadas diversas áreas em que a aritmética intervalar tem muito a oferecer. O autor também
lista várias aplicações, principalmente científicas e da engenharia, em que a aritmética intervalar
é utilizada exitosamente. Fontes bibliográficas, conferências sobre o tema, softwares diversos para
aritmética intervalar, dentre outros, são também apontados pelo autor.

2.2 Computação verificada e resolução de SELAs


A maneira mais simples de se realizar computação verificada é substituir as operações em ℜ
por sua equivalente intervalar e, então, executar a computação utilizando aritmética intervalar.
Dessa forma, produz-se resultados confiáveis. Porém, em geral, o diâmetro dos intervalos, ou
seja, a distância entre x e x, é tão grande que o resultado torna-se inútil. Logo, métodos mais
sofisticados fazem-se necessários. Tais métodos consistem em uma combinação dos benefícios da
aritmética intervalar com um mecanismo de refinamento dos intervalos encontrados, de forma que
seu diâmetro seja o menor possível contendo o resultado exato [15]. O refinamento iterativo é
um processo bastante simples. Basicamente, dada uma solução inicial, repete-se o cálculo para
diminuir o erro da mesma até que o tamanho do intervalo seja menor do que a exatidão desejada.
Assim, a aproximação verificada é dada pelo intervalo somado ao erro. Esses métodos, em geral,
obtêm êxito em encontrar uma aproximação suficientemente útil da solução e, caso contrário,
notificam o usuário de que a computação falhou. Por outro lado, na aritmética de ponto flutuante
convencional, a computação pode falhar sem que qualquer sinal seja dado ao usuário [23, 21].
Conforme visto anteriormente, o passo de verificação pode resultar em falsos positivos devido
a erros de programação. Além disso, como os dados de entrada estão sujeitos a erros de conversão,
o usuário precisa estar atento ao fato de que se os dados sofrerem efetivamente tais erros, então
o resultado do passo de verificação será válido apenas para os dados convertidos e não para os
dados de entrada decimais originais. Assim, para evitar confusões, é recomendado que se faça
um checagem de se os dados de entrada são representáveis de maneira exata em F. Existem
algumas maneiras de fazer tal verificação em tempo de execução. Por exemplo, a biblioteca C-
XSC converte um número real representando por um literal (string) para o formato de ponto
flutuante utilizando o arredondamento corrente. Assim, um intervalo contendo o número exato
pode ser formado compondo a representação em literal arredondada diretamente para cima com
ela mesma arredondada diretametne para baixo. Se o diâmetro do intervalo composto for zero,
então o número é representável de maneira exata [15, 18].
Muitos dos algoritmos para verificação numérica são baseados na aplicação dos teoremas de
ponto fixo clássicos. Por exemplo, a convergência é garantida pelo Teorema de Ponto Fixo de
Brouwer [17]. Seja X = [x] ∈ Iℜn um vetor intervalar em ponto flutuante, o qual satisfaz as
condições do Teorema de Ponto Fixo de Brouwer. Supondo que é possível encontrar f tal que
f ([x]) ⊆ [x], então [x] é comprovadamente uma aproximação de pelo menos um ponto fixo x∗ de f .
A afirmação permanece válida substituindo-se f por sua avaliação intervalar em ponto flutuante
f⋄ , pois f⋄ ([x]) ⊆ [x] implica f ([x]) ⊆ [x] uma vez que f ([x]) é subconjunto de f⋄ ([x]). O Teorema
de Ponto Fixo de Brouwer combinado com a aritmética intervalar permite a computação numérica
provar a existência e unicidade das soluções para sistemas lineares e não-lineares [15, 17].
Versões intervalares de praticamente todos os métodos clássicos para resolução de SELAs estão
disponíveis, porém, no geral elas diferem bastante de suas versões tradicionais. Por exemplo,
em geral o sistema A~x = ~b precisa ser pré-condicionado com uma matrix pontual para que os
algoritmos sejam eficientes. Na prática, costuma-se calcular uma solução aproximada para o
sistema pontual utilizando softwares como LINPACK e LAPACK e, então, utilizar essa solução na
obtenção dos limites para formar um intervalo no qual se sabe que a solução exata está contida [17].
A seguir o Método Baseado no Método de Newton, o qual será utilizado na presente proposta,
é apresentado. Sua descrição completa, bem como uma implementação seqüencial do mesmo
utilizando C-XSC, encontra-se em [15].
2. Computação verificada e sua aplicação na resolução de SELAs 11

2.2.1 Método Baseado em no Método de Newton


Seja A~x = ~b um sistema de equações, encontrar a solução do sistema é equivalente a encontrar a
raiz de uma função f (x) = A~x − ~b. Assim, o Método de Newton gera a seguinte iteração de ponto
fixo, onde x(0) é algum valor inicial arbitrário qualquer [15]:
 
x(k+1) = x(k) − A−1 Ax(k) − b , k = 0, 1, . . . (2.6)

Em geral, a inversa exata de A não é conhecida. Assim, ao invés de (2.6), a chamada Newton-
like Iteration 1 é utilizada, onde R ≈ A−1 é uma inversa aproximada de A:
 
x(k+1) = x(k) − R Ax(k) − b , k = 0, 1, . . . , (2.7)
(k)
Substituindo a iteração real x(k) por vetores intervalares [x] ∈ Iℜn , se existe um índice k
(k+1) (k)
com [x] ⊂ [x] , então, pelo Teorema de Ponto Fixo de Brouwer, a Equação 2.7 tem pelo
menos um ponto fixo x ∈ [x](k) . Supondo que R é regular, então esse ponto fixo é também uma

(k+1) (k+1)
solução para A~x = ~b. Entretanto, considerando o diâmetro de [x] , obtém-se: d [x] =
      
(k) (k+1) (k)
d [x] + d R A [x] −b ≥ d [x] . Assim, em geral, a relação de subconjunto não
é satisfeita. Por essa razão, o lado direito de (2.7) é modificado para a equação a seguir, onde I
denota a matriz identidade n x n [15]:

x(k+1) = Rb + (I − RA) x(k) , k = 0, 1, . . . , (2.8)


(k+1) ◦ (k)
Sabe-se que se existe um índice k com [x] ⊂ [x] , então as matrizes R e A são regulares
~ (k+1)
e existe uma solução única x do sistema A~x = b com x ∈ [x] . Esse resultado permanece
válido para qualquer matriz R. Entretanto, é um fato empírico que quanto mais R se aproxima
da inversa de A, mais rapidamente o método converge. Uma algoritmo bastante eficiente para
inversão de matrizes, o qual baseia-se no Algoritmo de Crout e adiciona pivotamento parcial ao
mesmo é apresentado por [15].
Adicionalmente, é um princípio numérico bem estabelecido que uma solução aproximada x̃ de
A~x = ~b pode ser melhorada resolvendo-se o sistema Ay = d, onde d = b − Ax̃ é o resíduo de
Ax̃. Uma vez que y = A−1 (b − Ax̃) = x − x̃, a solução exata de A~x = ~b é dada por x = x̃ + y.
Aplicando a Equação 2.8 ao sistema residual, obtém-se o Esquema de Iteração Residual [15]:

y (k+1) = R (b − Ax̃) + (I − RAx̃) y (k) , k = 0, 1, . . . (2.9)


| {z } | {z }
=:z =:C

A equação residual Ay = d tem uma solução única y ∈ [y](k+1) ⊂ [y](k) para a iteração
(k+1)
intervalar correspondente. Além disso, uma vez que y = x − x̃ ∈ [y] , uma solução verificada
(k+1)
da solução única de A~x = ~b é dada por x̃ + [y] . Esses resultados permanecem válidos ao
substituir as expressões exatas z e C em (2.9) por extensões intervalares. Entretanto, para diminuir
os efeitos de overestimation, recomenda-se fortemente avaliar b−Ax̃ e I −RA sem arredondamentos
intermediários.
Por fim, tem-se que o condicionamento de uma matriz regular quadrada A é definido pela
Equação 2.10. Ao resolver um sistema de equações lineares com aritmética tradicional de ponto
flutuante, via de regra log (cond (A)) é um indicador grosseiro do número de casas decimais per-
didas de exatidão na solução. Por exemplo, um condicionamento de 105 sinaliza uma perda em
torno de cinco casas decimais de exatidão [15].

cond (a) := ||A||∞ . A−1 ∞ (2.10)

1 Não há uma tradução exata no português para o nome do método. Pode-se enteder algo próximo de Iteração

Baseada no Método de Newton


3 Arquiteturas de memória
compartilhada

A compreensão do inter-relacionamento entre as características de um algoritmo paralelo e as da


arquitetura em que ele irá executar é fundamental para a qualidade ao trabalhar com processa-
mento paralelo. Para que se obtenha alto desempenho em arquiteturas paralelas deve-se buscar
equilíbrio entre as características do hardware e as do software. Neste capítulo é apresentada,
incialmente, a classificação de arquiteturas mais comumente adotada na computação enfatizando
as arquiteturas paralelas de memória compartilhada. Na seqüência, discute-se algumas questões
sobre a programação de arquiteturas paralelas.

3.1 Classificação das arquiteturas de computador


As arquiteturas de memória compartilhada, também conhecidas como multiprocessadores, são
uma subdivisão da classificação das máquinas paralelas originalmente proposta por [13] na qual
todas as máquinas paralelas pertenciam à categoria MIMD (Multiple Instruction Streams Multiple
Data Streams, Múltiplos Fluxos de Instruções Múltiplos Fluxos de Dados). Com o passar dos
anos, o aumento da complexidade e da variedade de arquiteturas fez com que essa classificação
já não bastasse para diferenciar as máquinas paralelas existentes. Assim, a mesma foi subdivida,
considerando o compartilhamento de memória, em duas subclasses [12]:

• Multiprocessadores: são as arquiteturas cujos processadores compartilham memória (shared


memory). Nesse caso, independentemente de a memória estar implementada de forma dis-
tribuída (distributed memory) ou centralizada (centralized memory), todos os processadores
compartilham um mesmo espaço de endereçamento e se comunicam através de operações de
escrita e leitura em variáveis compartilhadas (programação multithread );
• Multicomputadores: arquiteturas que possuem múltiplos espaços de endereçamento privado
(multiple private address spaces), ou seja, cada processador possui um espaço próprio. A
implementação da memória é sempre distribuída e os processadores se comunicam por trocas
de mensagens utilizando para isso bibliotecas como MPI.

Ambas as categorias acima subdividem-se ainda de acordo com a latência no acesso à memória.
No caso das máquinas de memória compartilhada, as quais são o foco da presente proposta, a
subdivisão é em duas subcategorias:

• UMA - Uniform Memory Access (Acesso Uniforme à Memória): computadores nos quais a
latência de acesso à memória é igual (uniforme) para todos os processadores que compõem
o sistema, independentemente da rede de interconexão utilizada ou de as transações serem
únicas ou paralelas. A implementação da memória é centralizada, ou seja, encontra-se à
mesma distância de todos os processadores.
• NUMA - Non-Uniform Memory Access (Acesso Não Uniforme à Memória): arquiteturas nas
quais a latência de acesso à memória não é uniforme. Cada processador é ligado diretamente
a um módulo de memória e acessa os demais módulos do sistema por meio dos outros

12
3. Arquiteturas de memória compartilhada 13

procesadores. Logo, a implementação da memória é distribuída e a latência de acesso depende


de se o endereço referenciado está ou não na memória diretamente ligada ao processador que
o referenciou.

As arquiteturas consideradas nesta proposta são as do tipo NUMA e as multi-core, as quais,


devido ao fato de serem recentes e possuírem características que não se encaixam totalmente em
nenhuma das classificações, serão consideradas no decorrer do texto como pertencentes à categoria
UMA. É importante, porém, ressaltar que, de acordo com [2], os processadores multi-core não
podem ser vistos como sendo um novo tipo de SMP e nem mesmo como semelhantes aos com-
putadores com múltiplos processadores. Isso porque, os processadores multi-core compartilham
recursos dentro de um mesmo chip, como por exemplo barramento e, muitas vezes, a memória
cache, enquanto em outros casos cada core possui uma cache própria. Portanto, as características
de um processador multi-core, embora semelhantes às máquinas UMA tradicionais, apresentam
particularidades que influenciam na forma como as mesmas devem ser programadas.
Existe, ainda, uma terceira subdivisão na hierarquia a qual classifica as arquiteturas de acordo
com o tratamento da coerência de cache. São quatro as variações possíveis: NCC-NUMA - Non-
Cache-Coherent Non-Uniform Memory Access (Acesso Não Uniforme à Memória Sem Coerência
de cache); CC-NUMA - Cache-Coherent Non-Uniform Memory Access (Acesso Não Uniforme à
Memória Sem Coerência de Cache); SC-NUMA - Software-Coherent Non-Uniform Memory Access
(Acesso Não Uniforme à Memória Com Coerência de Cache em Software); e COMA - Cache Only
Memory Architeture (Arquiteturas com somente memória cache). A Figura 3.1 apresenta por
completo a classificação utilizada [12].

Figura 3.1: Classificação das arquiteturas paralelas segundo critérios relativos à memória [12].

3.2 Programação em arquiteturas paralelas


Ao desenvolver aplicações para agregados de computadores, como é o caso dos trabalhos relaciona-
dos apresentados na introdução desta proposta, as principais preocupações são com a sincronização
entre os processos, tolerância a falhas e com diminuir o máximo possível a necessidade de comu-
nição, uma vez que a comunicação naquele tipo de arquitetura é custosa. A comunicação nesses
casos torna-se custosa principalmente devido à utilização da rede pelo paradigma de troca de men-
sagens. Em máquinas de memória compartilhada o paradigma de troca de mensagens introduz
custos extras e operações de cópia/escrita na memória desnecessários, o que diminui o desempenho
e torna mais difícil o escalonamento de atividades que podem ser executadas em paralelo. Logo,
a comunicação é feita, nessas arquiteturas, por operações de leitura e escrita em variáveis com-
partilhadas. A sincronização é também uma preocupação bastante presente, porém é tratada de
3. Arquiteturas de memória compartilhada 14

formas diferentes como, por exemplo, com o uso de semáforos. Faz-se necessário também controle
de acesso às seções críticas para evitar condições de corrida ou inconsistência nos dados e até
mesmo situações de impasse (deadlocks), o que, em geral, não é uma preocupação ao trabalhar
com multicomputadores.
A implementação de soluções paralelas tanto para máquinas multi-core quanto NUMA é feita
através do paradigma de multiprogramação leve, também chamado programação com processos
leves (multithread ). Utiliza-se, para isso, bibliotecas de programação com threads, sendo as duas
mais populares POSIX Threads (Pthreads) [27] e OpenMP (Open Multi-Processing) [26]. Tais
ferramentas diferem basicamente em relação ao nível de abstração que oferecem para criação,
destruição, comunicação e sincronização dos threads. De um lado encontra-se Pthreads, onde o
programador deve controlar explicitamente as operações acima citadas. Na outra ponta, está o
OpenMP em que o usuário, através de ‘comentários especiais’ chamados diretivas de compilação,
delimita os trechos do código que deverão ser paralelizados. Feito isso, o compilador gera automa-
ticamente o código paralelo. Ambas são portáveis tanto em termos de hardware como de software.
Entretanto, embora o paradigma de programação empregado nas máquinas de memória compar-
tilhada em geral seja o mesmo entre elas e diferente daquele utilizado nos multicomputadores, a
aplicação prática do mesmo apresenta características bastante diferentes mesmo entre as próprias
máquinas de memória compartilhada. Em geral, é mais simples desenvolver soluções paralelas
para explorar ao máximo os recursos de máquinas UMA tradicionais do que máquinas NUMA e
arquiteturas multi-core, pois nas últimas algumas questões de mais baixo nível costumam apare-
cer. Basicamente são três as questões de programação nas quais as máquinas NUMA diferem das
UMA: coerência de cache, localidade de dados e escalonamento de processsos.
A coerência de cache consiste em garantir que um dado lido é sempre o mais recente, ou seja,
após um valor em memória ser modificado por algum dos processadores, leituras futuras do mesmo
deverão retornar o conteúdo alterado, independentemente de qual processador o modificou/leu. Os
mecanismos que implementam a coerência são chamados de protocolos de coerência de cache e, em
geral, são implementados em hardware. A subdivisão das máquinas, anteriormente apresentada,
em NCC-NUMA, CC-NUMA, SC-NUMA e COMA trata justamente desta questão em nível de
arquitetura. Tais mecanismos influenciam fortemente o desempenho, pois refletem diretamente na
movimentação dos dados entre os níveis de memória. Logo, em máquinas NUMA a coerência de
cache passa a ser um preocupação presente no desenvolvimento da solução paralela, enquanto em
UMA isso não acontece.
Em relação à localidade dos dados na memória, sabe-se que, de modo geral, as caches agrupam
posições contíguas de memória em blocos. No momento em que um processo referencia pela
primeira vez um trecho da memória, o bloco completo é transferido da memória principal para
a cache. Assim, caso outro dado pertencente ao mesmo bloco seja referenciado, o mesmo não
precisará ser trazido da memória principal, o que reduz consideravelmente a latência de acesso.
Na resolução de SELAs percebe-se claramente a influência da cache no tempo de execução ao
comparar sistemas nos quais blocos completos, como por exemplo uma linha inteira da matriz A e
o vetor ~b, podem ser armazenados em cache com aqueles cujo tamanho é demasiadamente grande
para tal. A utilização de blocos advém de características naturais dos programas seqüenciais como
localidade espacial e temporal. A diferença entre as arquiteturas é que no caso de máquinas UMA
quando for necessário movimentar um dado da memória principal para a cache, o tempo de acesso
será uniforme, enquanto em máquinas NUMA o dado pode pertencer a um módulo de memória
próximo bem como a outro não próximo ao processador, havendo assim diferença nos tempos de
acesso. Ao trabalhar com máquinas NUMA é possível que o programador defina em que módulo
de memória determinado dado deve ser armazenado. Esse controle pode ser, também, delegado
ao sistema operacional (SO). Nesse caso, o SO altera a localidade dos dados conforme o programa
é executado, o que pode ser feito de duas maneiras: replicação ou migração de páginas. Logo, no
caso das máquinas NUMA é importante que o desenvolvedor conheça os mecanismos empregados
na gerência da memória, o que, em princípio, não acontece no caso das máquinas UMA.
A terceira questão, ou seja, o escalonamento, em máquinas costuma ser tratada com uma das
estratégias a seguir: timesharing, space sharing e gang scheduling. A mais comum delas, Timesha-
ring, é utilizada nas versões para multiprocessadores dos SOs Windows e Linux. Nesse método,
3. Arquiteturas de memória compartilhada 15

cada processo executa em um dos processadores por um intervalo de tempo ou até executar uma
operação bloqueante, quanto então, o escalonador seleciona o processo que ocupará o seu lugar. O
escalonamento dos threads ocorre de maneira semelhante ao escalonamento dos processos, sendo
que os SOs oferecem suporte aos threads de duas maneiras: através de preempção multithreading
ou multithreading cooperativa. Na primeira o SO determina quando executar trocas de contexto,
enquanto na segunda, o controle fica a cargo dos próprios threads. Entretanto, ao considerar má-
quinas NUMA, uma preocupação adicional, relativa ao balanceamento de carga, surge. Se um
processo p em um determinado processador localizado no nó n alocar dados em memória, tais
dados estarão em um módulo de memória de n. Porém, caso o sistema venha a ficar desbalan-
ceado, o algoritmo de balanceamento de carga poderá optar por migrar o processo p para outro
nó e, nesse caso, o tempo de acesso ao módulo de memória ficará comprometido, uma vez que
a memória alocada continuará no nó n porém o processo p não. Assim, alternativas, como por
exemplo migração de páginas, devem ser consideradas ao trabalhar com máquinas NUMA.
O tratamento dessas questões em máquinas NUMA pode ser feito utilizando-se a interface
de programação libnuma [19] a qual permite manipular o escalonamento dos threads, ou seja,
definir a qual processador cada thread será atribuído, e a alocação de memória definindo em que
módulo uma determinada região de memória deve ser alocada. A libnuma permite controlar
políticas sobre processos e regiões de memória em arquiteturas NUMA oferecendo uma interface
amigável de desenvolvimento por abstrair chamadas de sistema de baixo nível. Tais políticas
podem ser definidas para cada processo (process policy) ou por região de memória (virtual memory
area policy). A primeira é aplicada a todas as alocações de memória realizadas no contexto
do processo, enquanto a segunda permite que os processos determinem uma política para cada
bloco de memória em seu espaço de endereçamento. O emprego das funções de gerenciamento de
memória em conjunto com as funções de gerenciamento da localização dos threads permite que o
desenvolvedor controle os dados e processos de modo a utilizar melhor os recursos de máquinas
NUMA. Em arquiteturas multi-core as questões são bastante parecidas e pode-se utilizar, por
exemplo, programação multithread com afinidade de processador (thread affinity) oferecida pela
biblioteca pthreads para tratá-las.
4 Programação numérica de alto
desempenho

Nas duas últimas décadas, diversos algoritmos e softwares para resolução de problemas da álgebra
linear têm sido desenvolvidos visando alto desempenho e portabilidade. O resultado mais im-
portante dessa movimentação é a biblioteca BLAS (Basic Linear Algebra Subprograms), a qual é
utilizada como núcleo para desenvolvimento dos mais populares pacotes de software para álgebra
linear, tais como LINPACK e LAPACK, dentre outros. Este capítulo apresenta brevemente a bi-
blioteca BLAS e, na seqüência, os pacotes da família LAPACK, um software portável para álgebra
linear de alto desempenho em máquinas de memória compartilhada implementado utilizando a
BLAS.

4.1 Basic Linear Algebra Subprograms - BLAS


Originalmente, a BLAS foi especificada como um conjunto de subprogramas em Fortran 66 e,
após, Fortran 77. Com o passar dos anos, implementações de referência para Fortran 95 e C
foram publicadas. A BLAS se tornou a biblioteca de álgebra linear mais utilizada mundialmente,
pois além do bom desempenho alcançado pela mesma, o fato de desenvolver softwares em torno
de um núcleo comum é considerada uma boa prática de engenharia de software, a qual facilita
o desenvolvimento de aplicações. A BLAS original, hoje conhecida como Level 1 BLAS, executa
operações entre escalares e entre vetores e escalares. Com o surgimento das máquinas vetoriais,
máquinas com hierarquia de memória e arquiteturas de memória compartilhada surgiu a neces-
sidade de softwares que explorassem adequadamente tais arquiteturas. Assim, uma extensão da
BLAS original, hoje conhecida como Level 2 BLAS, surgiu, a qual executa operações entre vetores
e matrizes. Entretanto, freqüentemente a Level 2 BLAS não se adaptava bem aos computadores
com hierarquia de memória cujo processamento era de fato paralelo. Nesse contexto surgiu a Level
3 BLAS, a qual executa operações entre matrizes e matrizes. Tais operações são executadas em
blocos permitindo, assim, reuso dos dados enquanto um bloco encontra-se na cache ou na memória
local, o que evita movimentação excessiva dos dados pela hierarquia de memória.
Um exemplo de operação executada pela Level 1 BLAS é o cálculo do produto interno de um
vetor. Tais operações envolvem complexidade de dados da ordem O (n) e custo computacional
também da ordem de O (n). Na Level 2 BLAS, as operações
 envolvem custo computacional de
O n2 com complexidade de dados também de O n2 . Um exemplo de operação realizada neste
nível é o produto entre um vetor e uma matriz. Por fim, na Level 3 BLAS, um exemplo de
operação é a multiplicação de duas matrizes. A complexidade de dados nesse nível é de O n2
e o custo computacional da ordem de O n3 . Basicamente, essas ordens de complexidade que
levaram à adoção dos nomes Level 1, 2 e 3. No contexto da presente proposta a Level 3 BLAS é
a de maior interesse. Diversos trabalhos comprovaram que a abordagem de particionamento dos
dados em blocos utilizada pela Level 3 BLAS permite explorar melhor o paralelismo e diminui
a movimentação excessiva dos dados na hierarquia de memória. Os algoritmos nesse nível são
implementados em termos de operações em submatrizes e as matrizes são armazenadas na memória
na forma de vetores bi-dimensionais.
As rotinas da BLAS estão disponíveis livremente na internet. Entretanto, a maioria dos fabri-

16
4. Programação numérica de alto desempenho 17

cantes de computadores oferece versões proprietárias das mesmas otimizadas para suas arquitetu-
ras. Em alguns casos tais versões estão também disponíveis gratuitamente, em outros é necessário
que o desenvolvedor pague por elas. Além disso, existem ainda disponíveis gratuitamente na
internet diversas implementações alternativas da BLAS construídas sob diferentes abordagens.
Uma das mais populares é a ATLAS (Automatically Tuned Linear Algebra Software) [33, 32], a
qual consiste em um pacote que analisa a arquitetura de hardware e gera, automaticamente, uma
versão otimizada da BLAS para a mesma. Outra implementação bastante importante é a Goto
BLAS [14], a qual ao invés de focar apenas na diminuição do movimento dos dados na memória
preocupa-se também com a redução das chamadas TLB misses, que são as tentativas de acesso a
entradas inexistentes na tabela do Translation Look-aside Buffer (TLB). Tanto a Goto BLAS como
a grande maioria das implementações proprietárias da BLAS utilizam recursos de multithread.
Cabe ainda observar a existência de uma versão paralela da BLAS para multicomputadores, a
PBLAS (Parallel Basic Linear Algebra Subprograms) [5], a qual está disponível para qualquer sis-
tema com suporte a MPI ou PVM. A PBLAS foi construída utilizando como bases a versão seqüen-
cial da BLAS e a biblioteca BLACS (Basic Linear Algebra Communication Subprograms) [11], uma
biblioteca desenvolvida para facilitar o desenvolvimento de programas de álgebra linear em ambi-
entes com troca de mensagens. Os trabalhos relacionados apresentados no início desta proposta
foram implementados com a PBLAS, entretanto, como a presente proposta é focada em máquinas
de memória compartilhada, versões seqüenciais ou multithread da BLAS tradicional devem ser
empregadas.

4.2 LINPACK, LAPACK e ScaLAPACK


Os pacotes LINPACK, LAPACK e ScaLAPACK são conjuntos de rotinas de software para ál-
gebra linear implementados com base na BLAS. Basicamente, a diferença entre eles é o tipo de
arquitetura em que estão focados. O LINPACK é o mais antigo deles e foi o primeiro a explorar
eficientemente as subrotinas da BLAS. É baseado na Level 1 BLAS e foi desenvolvido para os su-
percomputadores existentes nos anos 70 e 80. O LINPACK utiliza algoritmos orientados a coluna,
ou seja, os vetores são referenciados por colunas e não por linhas. Essa opção é devido ao fato
de o Fortran armazenar vetores em colunas. Por volta dos anos 80, percebeu-se a existência de
uma lacuna entre o desempenho dos processadores e memórias e, então, surgiu a necessidade de
reformular os algoritmos em termos de operações entre matrizes e matrizes, ou seja, operações da
Level 3 BLAS. Nesse contexto surgiu, como sucessor do LINPACK, o LAPACK.
O desenvolvimento do LAPACK deu-se nos anos 80 com o objetivo de fazer as já famosas
bibliotecas EISPACK e LINPACK rodarem eficientemente em supercomputadores vetoriais de
memória compartilhada. Nessas arquiteturas o LINPACK e EISPACK eram ineficientes pelo fato
de seus padrões de acesso à memória desrespeitarem a hierarquia de memória com múltiplas ca-
madas dessas máquinas. O LAPACK explora a Level 2 BLAS e obteve bom desempenho em
todas as arquiteturas de memória compartilhada da época melhorando seus antecessores em qua-
tro aspectos principais: velocidade, exatidão, robustes e funcionalidades. A estratégia utilizada
para reduzir a movimentação dos dados entre a hierarquia de memória e, assim, obter ganhos de
desempenho foi a de reorganizar os algoritmos para usarem operações de matrizes em blocos nos
laços mais internos. Essas operações em bloco podem ser otimizadas para cada arquitetura, o que
resulta em portabilidade por permitir obter alto desempenho na maioria das máquinas moder-
nas. O LAPACK suporta matrizes densas e do tipo banda, mas não matrizes esparsas. Nos anos
90, com o advento e popularização dos aglomerados de computadores, uma versão do LAPACK
para arquiteturas de memória distribuída que se comunicam através de troca de mensagens foi
desenvolvida, o ScaLAPACK.
O ScaLAPACK começou a ser desenvolvido em 1991 e foi publicado em 1994. É um pacote
de software que extende a biblioteca LAPACK para execução escalável em agregados de compu-
tadores. Nessas máquinas, a hierarquia de memória é formada também por memórias externas à
cada nó, além dos registradores, cache e memória local de cada processador. O ScaLAPACK foi
desenvolvido utilizando o paradigma Single-Program-Multiple-Data (SPMD) com troca de men-
4. Programação numérica de alto desempenho 18

sagens explícita para comunicação entre processadores heterogêneos que suportem MPI ou PVM.
Da mesma forma que no LAPACK, as rotinas do ScaLAPACK são baseadas no particionamento
em blocos dos algoritmos e assume-se que as matrizes são armazenadas em blocos bi-dimensionais.
Os níveis 1, 2 e 3 da implementação paralela da BLAS, PBLAS, são utilizados no ScaLAPACK
em conjunto com a BLACS. Além disso, uma das metas no desenvolvimento do ScaLAPACK foi
manter as chamadas para suas rotinas tão semelhantes quanto possível às chamadas do LAPACK,
facilitando assim os esforços de implementação dos usuários. Para atingir escalabilidade, além do
particionamento em blocos de tamanhos ajustáveis dos algoritmos, o ScaLAPACK possui diversos
algoritmos equivalentes para um mesmo cálculo permitindo assim a escolha, em tempo de execu-
ção, do melhor algoritmo para uma dada entrada ou arquitetura em execução. Por fim, o modo
como os dados são distribuídos pelos processos tem grande impacto no balanceamento de carga e
nos custos da comunicação. A distribuição cíclica em blocos, a qual é utilizada pelo ScaLAPACK,
provê um mecanismo simples para distribuição de dados com algoritmos particionados em blocos
em arquiteturas de memória distribuída.
5 Proposta para a Dissertação de
Mestrado

Neste capítulo é apresentada a proposta para a Dissertação de Mestrado. Primeiramente é explici-


tada a motivação para a realização do trabalho. Na seqüência, os objetivos que se pretende alcançar
com a execução do mesmo são apresentados. Após, a metodologia que deverá ser adotada no de-
senvolvimento do trabalho é exposta, incluindo algumas das ferramentas que se pretende utilizar.
Por fim, é descrita uma lista de atividades e suas relações com os períodos de tempo disponíveis
para executá-las dentro do escopo da Dissertação.

5.1 Motivação
A necessidade de ferramentas para computação verificada se justifica para as aplicações científicas
e de engenharia onde o rigor dos resultados computados é um requisito indispensável. Conforme
visto anteriormente, as ferramentas de computação verificada exigem a utilização da aritmética
intervalar. Porém, além de ser uma exigência, a aritmética intervalar é, concomitantemente, uma
motivação, pois permite trabalhar com dados incertos, o que não é possível através de sistemas
com números pontuais. Dados incertos são aqueles cujo valor não se conhece exatamente, então ao
invés de representá-los por um número real faz-se a representação com a utilização de um intervalo
dentro do qual sabe-se que o dado está contido. Em geral, dados desse tipo ocorrem com bastante
freqüência em problemas científicos e de engenharia, uma vez que os processos de modelagem
por si só costumam conter um erro inerente. Além disso, nos casos em que se utiliza simulações,
os erros de arredondamento das máquinas podem introduzir incertezas nos dados, assim como,
naqueles casos em que fenômenos são mensurados com o uso de instrumentos, a exatidão dos dados
é afetada pelos próprios instrumentos empregados.
Na presente proposta optou-se por trabalhar com a aritmética intervalar na notação de ponto
médio e raio. Tal opção foi motivada pela revisão bibliográfica realizada em [25], de onde concluiu-
se que é a representação mais adequada para o presente contexto. Isso porque a aritmética de
ponto médio e raio permite a utilização de operações puramente de ponto flutuante, o que permite
maior desempenho e não é possível com a representação por ínfimo supremo. Isso porque, ao
utilizar operações puramente de ponto flutuante, as bibliotecas numéricas altamente otimizadas,
como BLAS e LAPACK, podem ser empregadas no desenvolvimento. Tal vantagem foi comprovada
por [21], onde resultados bastante satisfatórios foram obtidos utilizando-se aritmética de ponto
médio e raio. O fator de speed-up obtido foi próximo do linear em aglomerados de computadores.
Entretanto, dadas as grandes mudanças que vêm ocorrendo na computação nos últimos anos
com o surgimento e popularização dos processadores multi-core e máquinas NUMA, é de urgente
interesse que resultados como os obtidos por [21] para aglomerados possam ser também obtidos
nessas máquinas de memória compartilhada.
De fato é difícil prever os impactos e a magnitude da descontinuidade que a computação de alto
desempenho está para experimentar com as novas gerações de máquinas paralelas heterogêneas e
multi-core. Empresas top de linha como a Intel anunciam já possuir processadores multi-core com
80 núcleos de processamento. Nesse contexto, a popularização dessas máquinas se suportada por
ferramentas adequadas pode permitir que as atividades de pesquisa as quais necessitam resolver

19
5. Proposta para a Dissertação de Mestrado 20

grandes sistemas lineares possam sair dos grandes centros de computação para também os médios
e pequenos laboratórios, os quais não possuem acesso a grandes aglomerados. Ademais, mesmo
os aglomerados de computadores modernos começam a ser construídos utilizando processadores
multi-core e, em alguns casos, cada nó do cluster é composto por máquinas NUMA com múltiplos
nós multi-core. Nesse contexto a exploração do paralelismo no nível atual não é suficiente para tirar
proveito de todas as características das novas máquinas, demonstrando a necessidade de aplicar
técnicas específicas de programação para as novas arquiteturas e, ao mesmo tempo, mesclá-las
com as estruturas de softwares já existentes.
Em [2] é apresentado o projeto PLASMA (Parallel Linear Algebra for Scalable Multi-Core
Architectures). Basicamente, a PLASMA consiste em uma nova biblioteca em desenvolvimento
pelos mesmos idealizadores do LINPACK, LAPACK e ScaLAPACK. De fato, de acordo com
os autores essa deverá ser a próxima geração dos pacotes de software para álgebra linear de
alto desempenho. O objetivo da PLASMA é justamente atacar as questões apresentadas para
o contexto atual da computação paralela, onde será necessário que os desenvolvedores explorem
o paralelismo em nível de threads com mecanismos mais eficientes para comunicação entre os
processadores e sincronização dos recursos. O paralelismo de instruções atualmente explorado em
hardware por pipelines superescalares terá de ser explorado em software.
O trabalho apresentado em [3] utiliza a computação paralela reorganizando o código e dados
de forma a tirar proveito das novas arquiteturas paralelas como NUMA dotadas de processadores
multi-core. Nesse caso o autor desenvolveu um sistema que paraleliza operações sob matrizes para
arquiteturas multi-core consdierando-as como blocos hierárquicos que servem como unidades de
dados sob as quais as operações são executadas e vistas como unidades de computação. Assim,
a implementação enfilera de modo transparente as operações requisitadas e verifica internamente
as dependências para então executá-las na melhor ordem possível de maneira semelhante a um
pipeline de microarquiteturas superescalares. Esse trabalho e, principalmente, o desenvolvimento
da biblioteca PLASMA, confirmam a necessidade e movimentação mundial para desenvolvimento
de software de álgebra linear de alto desempenho para esse novo nicho de arquiteturas.

5.2 Objetivos
O objetivo central da presente proposta é desenvolver uma ferramenta computacional para
resolução de SELAs densos, intervalares e de grande porte, a qual deve realizar veri-
ficação automática dos resultados e ser otimizada para execução de alto desempenho
em arquiteturas de memória compartilhada. Essa ferramenta deverá ser capaz de prover
resultados verificados para sistemas lineares em que os dados contidos nas matrizes e vetores são
intervalos ao invés de números pontuais. Tal implementação deverá tirar proveito das caracterís-
ticas presentes nas arquiteturas paralelas de memória compartilhada visando ganhar desempenho
de modo que seu tempo de execução seja satisfatório para o usuário.
Objetivos secundários aparecem como conseqüência da própria metodologia que será adotada,
tais como: investigar os algoritmos para resolução de SELAs de grande porte densos; revisar
profundamente a aritmética intervalar; realizar estudos aprofundados das arquiteturas de memória
compartilhada multi-core e NUMA; explorar as bibliotecas para programação multithread, tais
como pthreads e OpenMP e de gerenciamento de políticas, como, por exemplo, libnuma, em
arquiteturas paralelas; estudar de modo aprofundado as bibliotecas mais populares para álgebra
linear com alto desempenho, destacando dentre elas o LAPACK.

5.3 Metodologia
A metodologia a ser utilizada para a realização desse trabalho será como segue. Inicialmente, uma
ampla revisão dos algoritmos para resolução de SELAs densos de grande porte será feita. Tal
revisão terá como objetivo identificar qual o algoritmo mais adequado para a implementação do
presente trabalho, decisão essa que será determinada basicamente por um fator: adaptabilidade
5. Proposta para a Dissertação de Mestrado 21

do algoritmo para as arquiteturas de memória compartilhada, ou seja, a relação entre facilidade


de paralelização e potencial para ganho de desempenho nessas arquiteturas. Em paralelo, serão
estudadas de modo aprofundado as arquiteturas dotadas de processadores multi-core e arquiteturas
NUMA visando levantar as particularidades de cada uma delas para determinar quais as estratégias
capazes de produzir maiores ganhos para o problema em questão. Como resulado desse estudo
deverá decidir-se também se a ferramenta proposta neste trabalho será implementada focando
máquinas NUMA ou máquinas multi-core. Uma terceira possibilidade é implementar duas versões
da ferramenta, uma para cada tipo de arquitetura, embora, em princípio, optar-se-á por uma
delas.
Estudos aprofundados sobre aritmética intervalar serão também realizados, em especial da
aritmética baseada na notação de ponto médio e raio, uma vez que essa foi identificada como a
mais adequada para a presente proposta. Um levantamento amplo das bibliotecas de programação
a serem utilizadas será feito, tanto daquelas para desenvolvimento da programação paralela em
si, ou seja, bibliotecas de programação multithread, como OpenMP e pthreads, e bibliotecas para
gerência de políticas de acesso aos dados, como libnuma, quanto daquelas utilizadas para a parte
do desenvolvimento relativa à algebra linear, como por exemplo o LAPACK. O projeto PLASMA
será também acompanhado de modo a utilizar eventuais resultados do mesmo e/ou até mesmo a
biblioteca caso a mesma venha a ser terminada em tempo.
Uma vez escolhidas as ferramentas para o desenvolvimento da solução proposta, o algoritmo
será cuidadosamente analisado de modo a identificar onde concentra-se o maior custo computaci-
onal e quais as políticas/maneiras mais adequadas de minimizá-lo. Para isso uma implementação
seqüencial deverá ser feita e os tempos de execução para resloução de sistemas com tamanho
médio contabilizados. Feito isso, a solução paralela será modelada considerando sempre como
objetivo maior a redução do tempo final de execução final sem que isso influencie na exatidão
dos resultados. Uma vez modelada a solução, a mesma será implementada na(s) máquina(s) de
memória compartilhada escolhida(s) com as ferramentas já citadas e, por fim, diversos testes serão
realizados. Tais testes terão como objetivos medir os ganhos de desempenho, a escalabilidade e
portabilidade da solução desenvolvida, dentre outros fatores que podem vir a ser identificados no
decorrer do trabalho.

5.4 Cronograma de atividades


A Tabela 5.1 apresenta o cronograma relacionando temporalmente as atividades a serem desenvol-
vidas com os períodos de tempo disponíveis para execução da proposta durante o ano de 2009. As
atividades apresentadas na tabela serão desenvolvidas de acordo com a metodologia acima descrita
e os números das atividades apresentadas fazem referência aos seguintes passos:

1. Revisão dos algoritmos para resolução de SELAs densos de grande porte;


2. Estudos sobre as arquiteturas multi-core e arquiteturas NUMA;
3. Decisão da arquitetura e algoritmo para resolução de SELAs a serem utilizados;
4. Estudos aprofundados da aritmética intervalar, em especial da aritmética de ponto médio e
raio;
5. Estudo aprofundado de bibliotecas para programação multithread ;
6. Levantamento e estudo das bibliotecas para gerência de políticas de acesso à memória;

7. Revisão e aprofundamento de estudos sobre as bibliotecas para álgebra linear de alto desem-
penho;
8. Análise do problema e implementação seqüencial para levantamento dos custos computaci-
onais, paralelismo em potencial e estratégias de paralelização possíveis;
5. Proposta para a Dissertação de Mestrado 22

9. Modelagem da solução paralela;


10. Escrita e apresentação do seminário de andamento;
11. Implementação da solução paralela modelada;
12. Execução de testes de desempenho, escalabilidade, portabilidade, dentre outros, da ferra-
menta desenvolvida;
13. Redação da Dissertação de Mestrado;
14. Preparação para apresentação e defesa da Dissertação de Mestrado.

Atividade Jan. Fev. Mar. Abr. Mai. Jun. Jul. Ago. Set. Out. Nov. Dez.
1 X X - - - - - - - - - -
2 X X - - - - - - - - - -
3 - X - - - - - - - - - -
4 - X X X - - - - - - - -
5 - X X X - - - - - - - -
6 - - - X X - - - - - - -
7 - - - X X - - - - - - -
8 - - - - X X - - - - - -
9 - - - - - X X - - - - -
10 - - - - - - - X - - - -
11 - - - - - - X X X X - -
12 - - - - - - - X X X X -
13 - - - - - - X X X X X -
14 - - - - - - - - - - - X

Tabela 5.1: Cronograma das atividades a serem desenvolvidas no ano de 2009.


Referências Bibliográficas

[1] E. Anderson, Z. Bai, C. Bischof, L. S. Blackford, J. W. Demmel, J. J. Dongarra, J. Du Croz,


A. Greenbaum, S. Hammarling, A. McKenney, and D. Sorensen. LAPACK Users’ Guide.
SIAM, Philadelphia, PA, USA, 1999.
[2] A. Buttari, J. J. Dongarra, J. Kurzak, J. Langou, P. Luszczek, and S. Tomov. The impact
of multicore on math software. In Applied Parallel Computing. State of the Art in Scientific
Computing, volume 4699, pages 1–10, Berlin, 2008. Springer Lecture Notes in Computer
Science.
[3] E. Chan, F. G. V. Zee, P. Bientinesi, E. S. Quintana-Orti, G. Quintana-Orti, and R. van de
Geijn. Supermatrix: a multithreaded runtime scheduling system for algorithms-by-blocks. In
PPoPP ’08: Proceedings of the 13th ACM SIGPLAN Symposium on Principles and practice
of parallel programming, pages 123–132, New York, NY, USA, 2008. ACM.
[4] J. Choi, J. W. Demmel, I. Dhillon, J. J. Dongarra, S. Ostrouchov, A. P. Petitet, K. Stanley,
D. W. Walker, and R. C. Whaley. Scalapack: a portable linear algebra library for distributed
memory computers – design issues and performance. Computer Physics Communications,
97(1–2):1–15, 1996.
[5] J. Choi, J. J. Dongarra, S. Ostrouchov, A. P. Petitet, and D. M. H. Walker. Lapack working
note 100: A proposal for a set of parallel basic linear algebra subprograms. Technical report,
Knoxville, TN, USA, 1995.
[6] D. M. Claudio and J. M. Marins. Cálculo Numérico Computacional. Editora Atlas, São
Paulo, 3rd edition, 2000.
[7] F. C. da S. Filho. Modelagem de problemas de engenharia: solução de Equações Diferenciais
Parciais pelo Método dos Elementos Finitos. Revista Tecnologia, 1:134–144, 2005.
[8] P. N. da Silva. Equações Diferenciais Ordinárias, volume 1 of Cálculo Diferencial e Integral.
Rio de Janeiro, 1st edition, 2005.
[9] J. W. Demmel. Lapack: a portable linear algebra library for supercomputers. Computer-
Aided Control System Design, 1989., IEEE Control Systems Society Workshop on, pages 1–7,
Dec 1989.
[10] J. J. Dongarra, G. B. Moler, J. R. Bunch, and G. W. Stewart. LINPACK Users’ Guide.
SIAM, Philadelphia, PA, USA, 1979.
[11] J. J. Dongarra and R. C. Whaley. Lapack working note 94: A user’s guide to the blacs v1.1.
Technical report, Knoxville, TN, USA, 1997.
[12] C. A. F. De Rose e P. O. A. Navaux. Arquiteturas paralelas. Livros Didáticos. Sagra Luzzatto,
Porto Alegre, 1st edition, 2003.
[13] M. J. Flynn. Some computer organizations and their effectiveness. IEEE Transactions on
Computers, C-21(9):948–960, September 1972.

23
REFERÊNCIAS BIBLIOGRÁFICAS 24

[14] K. Goto and R. van de Geijn. On reducing tlb misses in matrix multiplication - flame working
note #9. Technical report, Austin, Texas, USA, 2002.
[15] R. Hammer, D. Ratz, U. W. Kulisch, and M. Hocks. C++ Toolbox for Verified Scientific
Computing I: Basic Numerical Problems. Springer-Verlag New York, Inc., Secaucus, NJ,
USA, 1997.
[16] B. Hayes. A lucid interval. American Scientist, 91(6):484–488, 2003.
[17] R. B. Kearfott. Interval computations: Introduction, uses, and resources. Euromath Bulletin,
2(1):95–112, 1996.
[18] R. Klatte, U. W. Kulisch, C. Lawo, R. Rauch, and A. Wiethoff. C-XSC - A C++ Class
Library for Extended Scientific Computing. Springer-Verlag, Berlin, 1993.
[19] A. Kleen. A NUMA API for LINUX. Novell Technical Linux Whitepaper, Whaltham, USA,
2005.
[20] M. L. Kolberg, L. Baldo, P. Velho, L. G. Fernandes, and D. M. Claudio. Optimizing a parallel
self-verified method for solving linear systems. In Applied Parallel Computing. State of the Art
in Scientific Computing, volume 4699, pages 949–955, Berlin, 2007. Springer Lecture Notes
in Computer Science.
[21] M. L. Kolberg, M. Dorn, G. Bohlender, and L. G. Fernandes. Parallel verified linear system
solver for uncertain input data. In Proceedings of 20th International Symposium on Computer
Architecture and High Performance Computing, pages 89–96, 2008.
[22] M. L. Kolberg, L. G. Fernandes, and D. M. Claudio. Dense linear system: A parallel self-
verified solver. International Journal of Parallel Programming, 36(4):412–425, 2008.
[23] U. W. Kulisch. Advanced Arithmetic for the Digital Computer: Design of Arithmetic Units.
Springer-Verlag New York, Inc., Secaucus, NJ, USA, 2002.
[24] D. Menard, D. Chillet, F. Charot, and O. Sentieys. Automatic floating-point to fixed-point
conversion for DSP code generation. In CASES ’02: Proceedings of the 2002 international
conference on Compilers, architecture, and synthesis for embedded systems, pages 270–276,
New York, NY, USA, 2002. ACM.
[25] C. R. Milani and L. G. Fernandes. An investigation on solving dense systems of linear equa-
tions with high performance verified computing on shared memory architectures. Trabalho
individual II - (mestrado em ciência da computação), Pontifícia Universidade Católica do Rio
Grande do Sul, 2008.
[26] OpenMP. The openmp api specification for parallel programming. Disponível em
http://openmp.org/wp/ - Acesso em 02 dez., 2008.
[27] Pthreads. Posix threads programming. Disponível em
https://computing.llnl.gov/tutorials/pthreads/ - Acesso em 02 dez., 2008.
[28] S. M. Rump. Solving algebraic problems with high accuracy. In Proc. of the symposium on A
new approach to scientific computation, pages 51–120, San Diego, CA, USA, 1983. Academic
Press Professional, Inc.
[29] S. M. Rump. Fast and parallel interval arithmetic. BIT Numerical Mathematics, 39(3):534–
554, 1999.
[30] S. M. Rump. Self-validating methods. Linear Algebra and Its Applications, 324(1-3):3–13,
2001.
REFERÊNCIAS BIBLIOGRÁFICAS 25

[31] M. Snir, S. Otto, S. Huss-Lederman, D. W. Walker, and J. J. Dongarra. MPI: The Complete
Reference. MIT Press, Cambridge, Massachusetts, USA, 1996.
[32] R. C. Whaley and J. J. Dongarra. Automatically tuned linear algebra software. In Supercom-
puting ’98: Proceedings of the 1998 ACM/IEEE conference on Supercomputing (CDROM),
pages 1–27, Washington, DC, USA, 1998. IEEE Computer Society.
[33] R. C. Whaley and A. P. Petitet. Minimizing development and maintenance costs in supporting
persistently optimized BLAS. Software: Practice and Experience, 35(2):101–121, February
2005.
[34] M. Zimmer and W. Krämer. Fast (parallel) dense linear interval systems solvers in C-
XSC using error free transformations and BLAS. In Annie Cuyt, Walter Krämer, Wolfram
Luther, and Peter Markstein, editors, Numerical Validation in Current Hardware Architec-
tures, number 08021 in Dagstuhl Seminar Proceedings, Dagstuhl, Germany, 2008. Internati-
onales Begegnungs- und Forschungszentrum für Informatik (IBFI).

Você também pode gostar