Computação Paralela e Distribuída

Propaganda
Computação Paralela e Distribuída
Profa. Cristina Boeres e Lúcia Drummond
Rio de Janeiro - 26 de fevereiro de 2007
Em convênio com:
IC – Instituto de Computação
UFF – Universidade Federal Fluminense
Introdução e Conceitos Básicos
• Por que computação paralela e distribuída
• Computação de Alto Desempenho
• Arquitetura de computadores
• Ambientes de programação paralela
• Modelos de programação paralela
Por que computação paralela e distribuída?
Sistemas de computadores seqüenciais cada vez mais velozes
– velocidade de processador
– memória
– comunicação com o mundo externo
Quanto mais se tem, mais se quer......
– Demanda computacional está aumentando cada vez mais: visualização, base de
dados distribuída, simulações, etc.
limites em processamento seqüencial
– velocidade da luz, termodinâmica
Por que computação paralela e distribuída?
que tal utilizar vários processadores?
dificuldades encontradas
– mas como?
– paralelizar uma solução?
E x ist e m v á rio s d e sa f io s e m C o m p u t a ç ã o P a ra le la e D ist rib u íd a
Computação de Alto Desempenho
Os grandes desafios (Levin 1989):
– química quântica, mecânica estatística e física relativista;
– cosmologia e astrofísica;
– dinâmica e turbulência computacional dos fluídos;
– projeto de materiais e supercondutividade;
– biologia, farmacologia, seqüência de genomas, engenharia genética, dobramento
de proteínas, atividade enzimática e modelagem de células;
– medicina, modelagem de órgãos e ossos humanos;
– clima global e modelagem do ambiente
Computação de Alto Desempenho
utilizando modelagem, simulação e análise computacional
Life Sciences
CAD/CAM
Aerospace
Digital Biology
Internet & Ecommerce
Military Applications
cortesia de RajKumar Buyya
Definindo melhor alguns conceitos
•
Concorrência
 termo mais geral, um programa pode ser constituído por mais de um
thread/processo concorrendo por recursos
•
Paralelismo
 uma aplicação é executada por um conjunto de processadores em um ambiente
único (dedicados)
•
Computação distribuída
 aplicações sendo executadas em plataformas distribuídas
Definindo melhor alguns conceitos
Qualquer que seja o conceito, o que queremos?
 estabelecer a solução do problema
 lidar com recursos independentes
 aumentar desempenho e capacidade de memória
 fazer com que usuários e computadores trabalhem em espírito de
colaboração
O que paralelizar?
Concorrência pode estar em diferentes níveis de sistemas computacionais
atuais
– hardware
– Sistema Operacional
– Aplicação
As principais questões que são focadas são
– Desempenho
– Corretude
– possibilidade de explorar o paralelismo
Por que paralelizar?
Aplicação Paralela
– várias tarefas
– vários processadores
• redução no tempo total de execução
Modelos de Programação Paralela
Criação e gerenciamento de processos
– estático ou dinâmico
Comunicação
– memória compartilhada
• visão de um único espaço de endereçamento global
–
memória distribuída
• troca explícita de mensagens
Modelos de Programação Paralela
Expressão de Paralelismo: Paradigmas
– SPMD
– MPMD
Metas
– aumento no desempenho
– maior eficiência
Objetivos
Visão geral
– arquitetura de computadores
– ambientes de programação paralela
– modelos de programação paralela
Motivar ⇒ Sistemas de Alto Desempenho
Arquitetura de Computadores
Classificação de Computadores
– Computadores Convencionais
– Memória Centralizada
– Memória Distribuída
Arquitetura de Computadores
Sistema Paralelo
– vários processadores
– vários módulos de memória
– comunicação: estruturas de interconexão
Plataforma de Execução Paralela
Conectividade ⇒ rede de interconexão
Heterogeneidade ⇒ hardware e software distintos
Compartilhamento ⇒ utilização de recursos
Imagem do sistema ⇒ como usuário o percebe
Escalabilidade ⇒ + nós > desempenho/eficiência
Classificação de Sistemas Paralelos
Proposta por Flynn
– quantidade de instruções e dados processados em um determinado momento
SISD (single instruction single data)
– Um contador de programa
– Computadores seqüenciais
SIMD (single instruction multiple data)
– Um contador de programa, uma instrução executada por diversos processadores
sobre diferentes dados
– Computadores
Classificação de Sistemas Paralelos
Proposta por Flynn
MISD (multiple instructions single data)
– Não aplicável
MIMD (multiple instructions multiple data)
– Vários contadores de programa
– Diferentes dados
– Os vários computadores paralelos e distribuídos atuais
Plataforma de Execução Paralela
Diferentes plataformas do MIMD de acordo com os seguintes critérios
–
–
espaço de endereçamento
mecanismo de comunicação
Podem ser agrupadas em quatro grupos
SMPs (Symmetric MultiProcessors)
MPPs (Massively Parallel Processors)
Cluster ou NOWs (Network Of Worstations)
Grades Computacionais
SMPs
SMPs ou Multiprocessadores
– único espaço de endereçamento lógico
• mecanismo de hardware (memória centralizada)
– comunicação ⇒ espaço de endereçamento compartilhado
• operações de loads e stores
– Acesso a memória é realizada através de leitura (load) e escrita (store),
caracterizando desta forma, a comunicação entre processadores
SMPs
Sistema homogêneo
Compartilhamento
– Compartilhamento total da mesma memória
Uma única cópia do Sistema Operacional
Imagem única do sistema
Excelente conectividade
– fortemente acoplados
Não escalável
Exemplos:
– Sun HPC 10000 (StarFire), SGI Altix, SGI Origin, IBM pSeries, Compac
AlphaServer
SMPs
Multiprocessadores
CPU
Memória
CPU
...
CPU
MPPs (Multicomputadores)
Diferem quanto a implementação física
Módulos ou elementos de processamento contendo:
– múltiplos processadores com memória privativa
– computadores completos
Espaço de endereçamento
– não compartilhado - memória distribuída
Comunicação
– troca de mensagens
Rede de interconexão
– diferentes topologias
Fracamente acoplados
Escaláveis
MPPs
Sistema homogêneo ou heterogêneo
Interconexão: redes dedicadas e rápidas
Cada nó executa sua própria cópia do Sistema Operacional
Imagem única do sistema
– visibilidade dos mesmos sistemas de arquivo
Um escalonador de tarefas
– partições diferentes para aplicações diferentes
MPPs
Partições dedicadas a cada aplicação
Aplicações não compartilham recursos
– Pode ocorrer que uma aplicação permaneça em estado de espera
Exemplos:
– Cray T3E, IBM SP2s, clusters
propósito de ser um MPP
montados pelo próprio usuário, com
MPPs

Multicomputadores
Escalonador
CPU
CPU
Mem.
Mem.
...
CPU
Mem.
requisições
Cluster de computadores ou NOWs
Conjunto de estações de trabalho ou PCs
Interconexão: redes locais
Nós: elementos de processamento = processador + memória
Diferenças em relação a MPPs:
–
–
não existe um escalonador centralizado
redes de interconexão tendem a ser mais lentas
Cluster de computadores ou NOWs
Resultado das diferenças:
–
–
–
Cada nó tem seu próprio escalonador local
Compartilhamento de recursos ⇒ sem partição dedicada a uma aplicação
Aplicação ⇒ deve considerar impacto no desempenho
⇒ não tem o sistema dedicado
– Possibilidade de compor um sistema de alto desempenho e um baixo custo
(principalmente quando comparados com MPPs).
Cluster ou NOWs
requisições requisições
CPU
CPU
Mem.
Mem.
...
requisições
CPU
Mem.
Grades Computacionais (Computational Grids)
Utilização de computadores
–
–
independentes
geograficamente distantes
Diferenças: clusters X grades
–
–
–
–
–
heterogeneidade de recursos
alta dispersão geográfica (escala mundial)
compartilhamento
múltiplos domínios administrativos
controle totalmente distribuído
Grades Computacionais
Componentes
–
–
PCs, SMPs, MPPs, clusters
controlados por diferentes entidades ⇒ diversos domínios administrativos
Não têm uma imagem única do sistema a princípio
– Vários projetos tem proposto o desenvolvimento de middlewares de
gerenciamento ⇒ camada entre a infra-estrutura e as aplicações a serem
executadas na grade computacional
Aplicação deve estar preparada para:
– Dinamismo
– Variedade de plataformas
– Tolerar falhas
Grades Computacionais
Sistema não dedicado e diferentes plataformas
– Usuários da grades devem obter autorização e certificação para acesso aos
recursos disponíveis na grade computacional
Falhas nos recursos tanto de processamento como comunicação são mais
freqüentes que as outras plataformas paralelas
– Mecanismos de tolerância a falhas devem tornar essas flutuações do ambiente
transparente ao usuário
Para utilização eficiente da grade computacional
– Gerenciamento da execução da aplicação através de políticas de escalonamento
da aplicação ou balanceamento de carga
– Escalonamento durante a execução da aplicação se faz necessário devido as
variações de carga dos recursos da grade
Grades Computacionais
usuário
usuário
Escalonador
de Aplicação
Escalonador
de Recursos
MPP
usuário
Escalonador
de Aplicação
Escalonador
de Recursos
SMP
Escalonador
de Recursos
Cluster
SMP
Grades Computacionais
Cluster
Workstation
MPP
Computador
convencional
Workstation
Internet
SMP
Servidor
SMP
MPP
Resumo
Plataformas de Execução Paralela
Características
Conectividade
Heterogeneidade
Compartilhamento
Imagem do Sistema
Escalabilidade
SMPs
excelente
nula
não
única
10
MPPs
muito boa
baixa
não
comum
1.000
NOWs
boa
média
sim
comum
1.000
Grids
média/ruim
alta
sim
múltipla
100.000
Top500 Supercomputer (atualizada)
Site
Computer
Procs
Year
Rmax
Rpeak
1
DOE/NNSA/LLNL
United States
BlueGene/L - eServer Blue Gene Solution
IBM
131072
2005
280600
367000
2
NNSA/Sandia National Laboratories
United States
Red Storm - Sandia/ Cray Red Storm, Opteron 2.4 GHz
dual
Cray Inc.
26544
2006
101400
127411
3
IBM Thomas J. Watson Research Center
United States
BGW - eServer Blue Gene Solution
IBM
40960
2005
91290
114688
4
DOE/NNSA/LLNL
United States
ASC Purple - eServer pSeries p5 575 1.9 GHz
IBM
12208
2006
75760
92781
5
Barcelona Supercomputing Center
Spain
MareNostrum - BladeCenter JS21 Cluster, PPC 970, 2.3
GHz, Myrinet
IBM
10240
2006
62630
94208
6
NNSA/Sandia National Laboratories
United States
Thunderbird - PowerEdge 1850, 3.6 GHz, Infiniband
Dell
9024
2006
53000
64972.8
7
Commissariat a l'Energie Atomique (CEA)
France
Tera-10 - NovaScale 5160, Itanium2 1.6 GHz, Quadrics
Bull SA
9968
2006
52840
63795.2
8
NASA/Ames Research Center/NAS
United States
Columbia - SGI Altix 1.5 GHz, Voltaire Infiniband
SGI
10160
2004
51870
60960
9
GSIC Center, Tokyo Institute of Technology
Japan
STSUBAME Grid Cluster - Sun Fire x4600 Cluster, Opteron
2.4/2.6 GHz and ClearSpeed Accelerator, Infiniband
NEC/Sun
11088
2006
47380
82124.8
Oak Ridge National Laboratory
United States
Jaguar - Cray XT3, 2.4 GHz
Cray Inc.
10424
2006
43480
54204.8
10
Rmax Maximal LINPACK performance achieved
GFlpos
Rpeak Theoretical peak performance
Top500 Supercomputer (Máquinas Brasileiras)
Site
Computer
Procs
Year
Rmax
Rpeak
273
Petroleum Company (C)
Brazil
xSeries Cluster Xeon 3.06 GHz – Gig-E
IBM
1024
2004
3755
6266.88
275
PETROBRAS
Brazil
Rbwr1 Cluster platform 3000 DL140G3 Xeon 3.06 GHz
GigEthernet
Hewlett-Packard
1300
2004
3739
7956
363
University of San Paulo
Brazil
BladeCenter JS21 Cluster, PPC970, 2.5 GHz, Myrinet
IBM
448
2006
3182.38
4480
418
PETROBRAS
Brazil
bw7 – Cluster platform 3000 DL140G3 Xeon 3.06 GHz
GigEthernet
Hewlett-Packard
1008
2004
2992
6169
Rmax Maximal LINPACK performance achieved
GFlpos
Rpeak Theoretical peak performance
Computação em Cluster
•
Um conjunto de computadores (PCs)
•
não necessariamente iguais  heterogeneidade
•
Filosofia de imagem única
•
Conectadas por uma rede local
Para atingir tais objetivos, necessidade de uma camada de software ou
middleware
Computação em Grid
•
Computação em Cluster foi estendido para computação ao longo dos sites
distribuídos geograficamente conectados por redes metropolitanas
Grid Computing
•
Heterogêneos
•
Compartilhados
•
Aspectos que devem ser tratados
•
Segurança
•
Falhas de recursos
•
Gerenciamento da execução de várias aplicações
Computação em Grid
O sonho do cientista (The Grid Vision)
Computação em Grid adota tanto o nome quanto o conceito semelhantes
aqueles da Rede de Potência Elétrica para capturar a noção ou a visão de:
−
−
−
−
Oferecer desempenho computacional eficientemente;
De acordo com a demanda;
A um custo razoável;
Para qualquer um que precisar.
O sucesso da computação em grid depende da comunidade de
pesquisadores
– A possibilidade de construir tal ambiente (hardware e software)
– Necessidade de atingir seus objetivos.
Computação em Grid
SETI@home: Search for Extraterrestrial Intelligence at Home
Computação em Grid
•
Grid middlewares: tem como objetivo facilitar a utilização de um ambiente
grid
• APIs para isolar usuários ou programas da complexidade deste ambiente
• Gerenciar esses sistemas automaticamente e eficientemente para executar
aplicações no ambiente grid (grid-enabled applications)
E as aplicações não habilitadas a execução em ambiente grids?
Computação em Grid
Como o usuário (dono da aplicação) escolhe?
Vários middlewares existem, qual o mais apropriado?
Vários estão ainda sendo desenvolvidos
Não há a garantia de suporte
Pouca comparação entre os middlewares, por exemplo, desempenho,
grau de intrusão.
É difícil encontrar grids com o mesmo tipo de software instalado
Algoritmos Paralelos
Definindo melhor alguns conceitos
Processamento Paralelo: processamento de informação concorrente que
pertencem a um ou mais processos que resolvem um único problema.
Processamento Distribuído: processamento de informações em um
sistema cujos recursos estão sendo compartilhados por vários programas
Computador Paralelo: computador de múltiplos processadores capaz de
realizar processamento paralelo
Supercomputador: computador de propósito geral capaz de resolver
problemas em alta velocidade, comparando com outras máquinas da
mesma época.
Terminologia
A vazão de um dispositivo é o número de resultados produzidos por unidade
de tempo. (throughtput)
Speedup (aceleração): razão entre o tempo de execução necessário para o
algoritmo sequencial mais eficiente e o tempo necessário para se realizar a
mesma computação numa máquina paralela
Existem diversas definições de speedup:
– speedup absoluto(n)= T(melhor alg. seq. )/ T( prog // c/ n proc.)
– speedup aproximado(n)= T(prog.// c/1 proc.)/T( prog // c/ n proc.)
– speedup relativo (n)= T(prog. // c/(n-1) proc.)/T(prog.// c/ n proc.)
Computação concorrente
Duas formas de se explorar a concorrência em computação em computação
– Paralelismo de controle e de dados
tempo t
7+3
string
10 +==“casa”?
200
32 +
* 329
33
14
Paralelismo de Controle
alcançado aplicando-se operações diferentes a diferentes dados
simultaneamente.
– fluxo de dados entre processos pode ser arbitrariamente complexo
Exemplo:
– Pipelining: cada estágio trabalha em velocidade plena sobre uma parte particular
da computação. A saída de um estágio é a entrada do estágio seguinte
Paralelismo de Controle
E1
E2
E3
E4
tempo
info 1
info 2
info 1
info 3
info 2
info 4
info 3
info 1
info 2
info 1
Paralelismo de Dados
uso de vários processadores para executar a mesma operação ao mesmo
tempo sobre elementos distintos de dados
Um aumento de k vezes no número de unidades funcionais levaria a um
aumento de k vezes a vazão do sistema
7+3
10 + 200
33 + 329
Aplicações
Aplicações ou programas podem ser executados mais rapidamente,
considerando duas formas de paralelismo
– tratar o programa seqüencial como uma série de tarefas
– cada tarefa = uma instrução ou blocos de instruções
OU
– especificar um programa paralelo, que resolve o problema através da
especificação de tarefas ou processos concorrentes
Exploração de paralelismo
Particionamento
– identificar em um programa, as tarefas que possam ser executadas em
paralelo (simultaneamente em mais de um processador)
– caso extremo: cada linha do programa correspondendo a uma tarefa
um bom desempenho só é alcançado se um número máximo de comandos são
executados simultaneamente
É preciso considerar dependências de dados
problema: se quase todos os comandos são dependentes
Exemplo: programa seqüencial  paralelismo de instruções
program nothing(){
input (A,B,C);
if A>B then {
C=A-B;
output (C);
} else {
C = B-A;
output (A,B,C)
}
A=0; B=1;
for i=1 to 3 {
input(C);
A=A+C;
B=B*C;
}
output (A,B,C);
}
Exemplo
Tarefa T1
input (A,B,C);
if A>B then{
C=A-B;
output (C);
}else{
C = B-A;
output (A,B,C)
}
Tarefa T2
A = 0;
Tarefa T3
B=1;
Tarefa T4
for i=1 to 3 {
input(C);
A=A+C;
B=B*C;
}
output (A,B,C)
Exemplo
T2
1
T3
T1
4
T4
16
1
Exemplo: Soma n números
P r o b l e m a : s o m a r nn ú m e r o s q u a i s q u e r
Programa sequencial:
read (n, vetor);
soma = 0;
for (i = 0; i < n; i++)
soma = soma + vetor[i];
Como paralelizar o problema?
Terminologias
•
Um algoritmo é escalável se o nível de paralelismo aumenta no mínimo
linearmente com o tamanho do problema.
•
Uma arquitetura é dita escalável se continua a alcançar o mesmo
desempenho por processador, mesmo para problemas maiores, com o
aumento de processadores.
– Se aplicável, o usuário pode resolver problemas maiores no mesmo intervalo de
tempo através da compra de uma máquina paralela com maiores dimensões
Algoritmos paralelos-de-dados são mais escaláveis do que algoritmos com
paralelismo de controle
– o nível de paralelismo de controle é geralmente constante, independente do
tamanho do problema, enquanto o nível do paralelismo de dados é uma função
crescente do tamanho do problema
Convergência entre Computação Paralela & Distribuída
•
Existia uma grande dificuldade de manter máquinas paralelas a frente aos
projetos de chip-único
– Computadores paralelos se tornaram mais difíceis de se construir e se usar do
que se esperava.
Motivo desta dificuldade: software
⇓
Paralelizar e gerenciar algoritmos paralelos não é uma tarefa fácil
Programação Paralela
•
No início dos anos 90: processamento paralelo foi retomado.
•
O problema de programação paralela seria bem mais difícil de atacar do
que se imaginava.
•
Pesquisa na área de programação em paralelo tem sido um tópico
importante.
Mas ao mesmo tempo....
Internet
•
Enquanto
muitos
estudavam
processamento
paralelo
associado
processadores ligados internamente em uma máquina, um outro grupo se
concentrava em paralelismo externo através de redes de computadores
•
a internet possibilitou a especificação de um tipo de paralelismo através de
uma conexões entre processadores
Sistema Paralelo e Distribuído
processamento distribuído renasceu como uma forma de paralelismo mais
lenta
computação distribuída e paralela são dois extremos num espectro de
computação concorrente
Sistema paralelo e distribuído é uma coleção de componentes de hardware
e software que otimizam o desempenho por problema, vazão de múltiplos
problemas e confiabilidade, ou uma combinação destes
Sistema Paralelo e Distribuído
• Problemas: a aglomeração de muitos processadores através de canais
de comunicação: o desempenho pode cair muito.
• Para alcançar o máximo dos sistemas paralelos e distribuídos:
projetistas e desenvolvedores de software precisam compreender a
interação entre hardware e software
Sistema Paralelo e Distribuído
computação distribuída é mais abrangente e universal do que
computação paralela
Paralelismo - forma restrita de computação distribuída
sistema paralelo : voltado à solução de um problema único no menor
tempo possível (otimização)
Computação distribuída é mais geral e reúne outras formas de
otimização...
Paralelismo é interessante ?
Na natureza, os eventos ocorrem em paralelo
programação seqüencial ordena eventos paralelos
essa ordenação dificulta a trabalho do compilador
mas, maior desempenho com o uso de paralelismo
–
no entanto,
não é trivial atingir alto desempenho em
computadores paralelos
aplicações
como
computacionalmente
os
Grandes
Desafios
são
limitados
Investindo em paralelismo
Dificuldades encontradas
pensar em paralelo é difícil
conhecimento em paralelismo é recente
pouco conhecimento sobre representações abstratas de computações
paralelas
Investindo em paralelismo
Em relação a características da máquina
Relação entre a velocidade do processador
– Elementos de processamento heterogêneos
Desempenho da interconexão de comunicação
– Latência de comunicação
– Congestionamento
– Topologia da rede
Hierarquia de memória
Tendência hoje:
– memória compartilhada distribuída
– superprocessadores distribuídos
Portabilidade
transferência de programas seqüenciais entre diferentes máquinas não é
tão custoso
mesmo não pode ser afirmado para sistemas paralelos
pode significar um re-projeto e re-implementação do software
qual é a melhor arquitetura paralela?
Quais características importantes das aplicações ?
Processos/tarefas
existe comunicação entre essas tarefas
– pode ser vantajoso executar várias tarefas em um só processador
– a tarefa perde o processador quando precisa de um dado a ser
comunicado
paralelismo virtual X real
– Por exemplo: existem 100 processadores disponíveis
– cada processador pode estar executando vários processos: virtualmente
existem um total de 300 processos
Quais características importantes das aplicações ?
difícil definir processos/tarefas totalmente independentes
– comunicação entre processos pode gerar um tráfego de mensagens
pesado
comunicação entre processos:
– troca de mensagens: considera a topologia da rede de interconexão
– memória compartilhada: utilização de semáforos para proteção de
regiões críticas
– direct remote-memory access: existência de processadores dedicados à
comunicação
Modelos de Computação Paralela
interface - uma máquina abstrata
a abstração se faz necessária para facilitar a programação sem se
preocupar com detalhes da máquina
– um modelo deve ser estável para ser um padrão
um modelo contém os aspectos importantes tanto para os projetistas
de software quanto para os da máquina
as decisões de implementações são feitas para cada máquina destino,
não havendo necessidade de se refazer programas
Aspectos Explorados pelo Modelo
Independência da arquitetura
Fácil entendimento
Aspectos Explorados pelo Modelo
Facilidade de programação
O programador não deve se preocupar com detalhes da máquina destino
– modelos abstratos: programação mais fácil
O compilador é que deve traduzir para uma estrutura do programa em
execução considerando o sistema computacional destino
– tarefa do compilador: mais árdua
nível de abstração
nível de máquina
Aspectos Explorados pelo Modelo
O modelo deve ser capaz de oferecer facilidades tais que seja fácil:
Decompor o programa em tarefas paralelas
Mapear as tarefas nos processadores físicos
– custo de comunicação
– heterogeneidade dos processadores
Sincronização entre tarefas: é preciso ter conhecimento do estado global da
estrutura de execução do programa (quando é necessário sincronizar?)
Abstraindo para Programar
Maior facilidade de programação: o esforço intelectual é reduzido quando
nos concentrarmos em "uma coisa de cada vez”
duas dimensões:
– dimensão espacial
– dimensão temporal
Dimensão Espacial
A cada momento, conjuntos de tarefas independentes são
implementadas
– cada tarefa ou processador não sabe o que acontecerá "a seguir"
detalhamento de informações globais levam a uma programação difícil
Dimensão Temporal
programas são composições de ações seqüenciais que preenchem o
sistema computacional como um todo:
pode-se definir com maior conhecimento o que vai acontecer a seguir
Níveis de Paralelismo
Dependendo do nível considerado, a exploração do paralelismo é diferente
nível de aplicações ou fases de aplicações
a nível de tarefas
a nível de instruções - a execução da instrução necessita da busca, análise
e execução propriamente dita
dentro dos circuitos aritméticos
Algoritmos
Quando queremos resolver um problema computacionalmente, temos
que analisar a complexidade deste. No domínio seqüencial, se procura
definir um algoritmo que resolva o problema em tempo mínimo.
Mas quando se tratando de algoritmos paralelos, mais um parâmetro
– número de processadores
– operações independentes devem ser executadas em paralelo.
qual o tamanho dos processos? noção de granulosidade (granularity)
– a razão entre o tempo de computação necessário para executar
uma tarefa e a sobrecarga de comunicação durante essa
computação.
Modelos de Computação
Modelo de Computação Sequencial: von Neumann
plataforma base para que usuários e projetistas
– complexidade de tempo do pior caso: tempo máximo que o
algoritmo pode levar para executar qualquer entrada com n
elementos
– complexidade de tempo esperado: complexidade média
– critério de custo uniforme: qualquer instrução RAM leva uma
unidade de tempo para ser executada e também o acesso a
registradores
Modelo de Computação Paralela
O desempenho do programa paralelo depende de certos fatores
dependentes da máquina:
– grau de concorrência;
– escalonamento e alocação de processadores;
– comunicação e sincronização.
Modelo PRAM – modelo ideal
conjunto de p processadores operando sincronamente sob o controle
de um único relógio, compartilhando um espaço global de memória
é possível que diferentes fluxos de instruções sejam executados
– aspecto não muito explorado pelos algoritmos
algoritmos desenvolvidos para este modelo geralmente são do tipo
SIMD
– todos os processadores executam o mesmo conjunto de
instruções, e ainda a cada unidade de tempo, todos os
processadores estão executando a mesma instrução mas usando
dados diferentes.
Modelo PRAM – modelo ideal
propriedades chaves:
– execução síncrona sem nenhum custo adicional para a
sincronização
– comunicação realizada em uma unidade de tempo, qualquer que
seja a célula de memória acessada
– comunicação é feita usando a memória global
Passo do algoritmo PRAM
fase de leitura: os processadores acessam simultaneamente locais de
memória para leitura. Cada processador acessa no máximo uma
posição de memória e armazena o dado lido em sua memória local
fase de computação: os processadores
aritiméticas básicas com seus dados locais
executam
operações
fase de gravação: os processadores acessam simultaneamente locais
de memória global para escrita. Cada processador acessa no máximo
uma posição de memória e grava um certo dado que está armazenado
localmente
Modelo PRAM
análise e estudo de algoritmos paralelos
definição de paradigma de programação paralela
avaliação do desempenho desses algoritmos independentemente das
máquinas paralelas
se o desempenho de um algoritmo paralelo para o modelo PRAM não é
satisfatório, então não tem sentido implementá-lo em qualquer que seja a
máquina paralela
se eficiente, no entanto, podemos simulá-lo em uma máquina real :
simulação deve ser eficiente
Padrões de Acesso no Modelo PRAM
Exclusive Read (ER): vários processadores não podem ler ao mesmo
tempo no mesmo local
Exclusive Write (EW): vários processadores não pode escrever no
mesmo local de memória
Concurrent Read (CR): vários processadores podem ler ao mesmo
tempo o mesmo local de memória
Concurrent Write (CW): vários processadores podem escrever no
mesmo local de memória ao mesmo tempo
Combinações são usadas para formar as variantes do PRAM:
EREW, CREW, ERCW e CRCW
Prioridades do CRCW
Para resolver conflitos no caso de vários processadores tentarem escrever
ao mesmo tempo no mesmo local de memória global:
Comum - vários processadores concorrem a escrita no mesmo local de
memória global durante o mesmo instante de relógio - todos devem
escrever o mesmo valor;
Arbitrário - dentre os vários processadores, um é selecionado
arbitrariamente e seu valor armazenado no local de memória
disputado;
Prioridade - dentre os vários processadores, aquele com o menor índice é
escolhido para escrever o seu valor no local concorrido.
Memória Global
P1
P2
P3
P4
Pn
Comunicação em uma máquina PRAM
Comunicação através da memória global: Pi quer passar x para Pj
– Pi escreve x em um local de memória global em um determinado
passo
– Pj pode acessar o dado naquele local no próximo passo
Memória compartilhada
d1
P1
d1
PASSO 12
P2
d2
P3
d3
Pn
dn
Observações
os processadores operam sincronamente: a cada
passo, todas os
processadores executam a mesma instrução sobre dados distintos
uma instrução pode ser simplesmente uma operação aritmética ou uma
comparação de dois números
processadores ativos: somente um subconjunto de processadores
executem uma instrução e processadores restantes ficam ociosos/inativos
Exemplo
V ⇒ vetor com n elementos.
x ⇒ um dado valor
Problema:
x∈V?
Ambiente: P processadores tipo EREW PRAM
Analisando o problema:
todos os processadores tem que saber o valor de x
não podem acessar a célula de x simultaneamente
depois, cada processador tem que olhar os elementos de V
sinalização da localização do valor x no vetor V
Solução
todos os processadores devem saber sobre x: broadcasting ou difusão
Pior caso deste procedimento log2 P passos
– P1 acessa a memória global:
– P2 comunica com P1 ou seja, de alguma forma, P1 informa x para P2
– P1 e P2 informam x para P3 e P4
– assim por diante
processadores não têm permissão de acesso simultâneo ⇒ gravam x
em lugares distintos: Mi é um dos P locais de memória global
Um vetor M auxiliar é utilizado
Solução do broadcasting (leitura)
P1 lê x
P1 escreve x em M1
P2 lê M1
P2 escreve em M2
P3 e P4 lêem M1 e M2
P3 e P4 escrevem em M3 e M4
P5, P6, P7 e P8 lêem M1, M2, M3 e M4
P5, P6, P7 e P8 escrevem M5, M6, M7 e M8
e assim por diante
a cada passo: duas vezes o número de processadores ativos do passo
anterior podem ler e escrever ⇒ log P passos
Memória compartilhada
x
x
x
x
x
M1
M2
M3
M4
M5
M6
P1
P2
P3
P4
P5
P6
x
x
x
x
x
x
PASSO 1
PASSO 2
PASSO 3
M7
M8
P7
PASSO 4
P8
A Procura
o vetor V é divido em P pedaços: S1, S2, …, SN
– Pi procura por x em Si
– pior caso: n/P passos
Total: log N + n/N passos, no pior caso
Como o algoritmo poderia ser melhorado??
– Definição de uma variável Achou
Com computador mais poderoso ⇒ algoritmo mais rápido.
PRAM mais poderoso: CREW PRAM
para achar x, o algoritmo executa n/P passos
leituras concorrentes são permitidas
– todos os processadores podem acessar x em um passo
– todos os processadores podem consultar Achou em um passo
– mas ao encontrar, o processador tem que atualizar Achou
Quantos passos nas seguintes situações?
– somente um dos elementos tem valor x
– x pode ser um valor repetido em V
• mais de um processador pode atualizar Achou
simultaneamente.
Relações entre Modelos
EREW PRAM ⇒ mais fraco
CREW PRAM ⇒ pode executar EREW na mesma quantidade de tempo
– simplesmente leituras concorrentes não são feitas
CRCW PRAM ⇒ pode executar EREW na mesma quantidade de tempo
– simplesmente leituras concorrentes não são feitas
Simulando Múltiplos Acessos em EREW
um só processador pode acessar a um local de memória a em um
determinado instante
o modelo é bastante flexível
– pode ser executado em qualquer outra PRAM
– permite a simulação de múltiplos acessos mesmo que o espaço de
armazenamento aumente ou o tempo de execução aumente
Simulando Múltiplos Acessos em EREW
Por que a simulação? O simulação pode ser necessária caso uma das
razões aconteça:
– se os computadores paralelos disponíveis são do tipo EREW então executar algoritmos tipo: CREW e CRCW através de
simulação
– para computadores paralelos com um grande número de
processadores:
• o número de processadores que podem acessar a um mesmo
local de memória simultaneamente é limitado
Simulando CW comum em um EREW
N acessos simultâneos por um EREW PRAM por N processos no mesmo
local
– leituras simultâneas: valor difundido, conforme já descrito: log N
passos
– escritas simultâneas: procedimento simétrico à difusão
CW comum:
todos processadores podem escrever no mesmo local de memória
global se o valor for o mesmo.
Suponha que Pi queira escrever o valor ai (1≤ i ≤ N)
variável auxiliar para cada processador Pi : bi
Simulando CW comum em um EREW
Dividindo a série ai em dois grupos
compare ai com ai+(N/2)
se forem iguais, Pi seta bi para verdadeiro (1)
Dividindo a série ai em quatro grupos
compare ai com ai+(N/4) e bi com bi i+(N/4)
se forem iguais, Pi seta bi para verdadeiro (1)
Memória compartilhada
a1
a2
a3 a4
a5
a6
a7 a8
5
5
5
5
5
5
5
P1
=
1
5
P2
=1
?
=
&
1
?
=
1
&
=
.......... b1 b2 b3 b4
== 1 ?
?
== 1 ?
=
1
P3
=1
=
1
&
1
?
?
== 1 ?
1=
1
?
P4
1=
?
Modelos Fortes e Fracos
O que quer dizer mais forte? Se um algoritmo é simulado em um
modelo mais fraco, o número de passos pode aumentar
CR ⇒ N leituras podem ser feitas concorrentemente
ER ⇒ uma leitura é feita por mais de uma passo
[EcKstein,1979][Vishkin,1983] p processadores CRCW com prioridade, é
simulado por um EREW PRAM com complexidade de tempo aumentado
por um fator Θ (log p).
em um CRCW com prioridade, os acessos simultâneos seria imediatos,
mas não no EREW
Algoritmos PRAM
para um problema: se um algoritmo PRAM tem complexidade de
tempo menor que a do algoritmo seqüencial ótimo, então o
paralelismo pode ser usado
Como iniciar um algoritmo PRAM: ativar os P processadores que farão
parte da computação
– os processadores serem ativados um a um
– através do algoritmo de difusão: log P passos
depois da ativação, o algoritmo paralelo pode ser executado
Identificando Paralelismo
paradigmas de computação paralela
algoritmos aqui falados consideram o modelo PRAM. Exemplos:
Árvore Binária: o fluxo de dados (e controle) se dá da raiz até as folhas
– Difusão: a partir de um processador, o fluxo (controle ou dados)
passa para dois processadores e assim, dobrando a cada iteração.
– Divisão e Conquista: um problema é subdividido em subproblemas
cada vez menores
ou contrário, das folhas até a raíz:
– Redução: dado n valores, a operação X é uma binária associativa
Redução: Soma
soma de n elementos: A = < 4, 3, 8, 2, 9, 1, 0, 5, 6, 3, 10, 2, 4, 7, 11, 3>
Soma_PRAM_Pi (){
Para
( 1≤ h ≤ log n  ) faça
se ( i ≤ n/2h  ) faça
A[i] := A[2i] + A[2i -1];
}
A[i] := A[2i] + A[2i -1]; ⇒ leitura: A[2i] e A[2i -1];
computa: A[2i] + A[2i -1];
escreve: A[i]
Memória compartilhada
32
17
4
7
3
10
8
2
10
15
9
1
0
5
5
46
21
6
9
3
10
12
2
25
11
4
7
14
11
3
P1
P2
P3
P4
P5
P6
P7
P8
7
10
10
5
9
12
11
14
17
32
78
15
21
46
25
Redução: Soma
primeiro loop: não há necessidade de mais do que n/2  processadores
processadores acessam dois locais de memória simultaneamente, mas
distintos
processadores escrevem em um local de memória (cada) simultaneamente,
mas distintos
para somar, log n iterações são necessárias, cada uma tem tempo
constante
Complexidade do Algoritmo: O ( log n) com O ( n/2  ) processadores
Noções de Complexidade
Existem algoritmos PRAM cuja complexidade de tempo é menor do que
o algoritmo correspondente seqüencial ótimo, mas podem
desempenhar mais operações do que o seqüencial
Complexidade de tempo do pior caso em função do tamanho da
entrada. Cada passo corresponde:
– uma fase de computação
– uma fase de comunicação
é importante especificar
– o número máximo de processadores usados, como função da
entrada
– o modelo arquitetural sendo usado
Noções de Complexidade
Paralelismo Limitado
algoritmo p-paralelo se implementado em um modelo com p
processadores, fixo
T(n) e P(n): o tempo de execução e a quantidade de processadores do
algoritmo paralelo
se o número de passos é T(n) considerando p processadores, então
esse algoritmo é p computável neste tempo
se T(n) é polinomial e p é limitado superiormente por polinômio, então
o número de processadores é limitado polinomialmente, senão,
ilimitado
Algumas Definições
A - algoritmo paralelo
n - o tamanho da entrada
Custo do Algoritmo Paralelo
produto tempo-processador T(n) × P(n)
–
ignora ociosidade de processador
Algoritmo paralelo de custo ótimo: Ts = T(n) × P(n)
– Ts o tempo de execução do melhor algoritmo seqüencial
p < P(n) processadores: cada processador executa sequencialmente o
que P(n)/ p processadores executam
– T(n) × P(n)/p unidades de tempo
Algumas Definições
Speedup , dado o número de processadores p
Se o S(A(n),p) é linear então todos os processadores são
efetivamente utilizados
– difícil de ser alcançado devido a natureza dos algoritmos e do
ambiente computacional paralelo
– difícil decompor o algoritmo em tarefas completamente
independentes, onde cada tarefa leva Ts /p unidades de tempo
para ser executada
Algumas Definições
Eficiência do algoritmo paralelo
razão entre S(A(n),p) e o número de processadores p
E(A(n),p) = S(A(n),p)/p
– mostra como os processadores são efetivamente utilizados: quanto
maior, melhor a utilização de cada processador
se E(A(n),p) = 1 o algoritmo paralelo é de custo ótimo
Algumas Definições
Trabalho de um Algoritmo Paralelo
um algoritmo é descrito como uma seqüência de unidades de tempo, onde
em cada unidade um conjunto de instruções concorrentes
trabalho de um algoritmo paralelo é o número total de operações
executadas, não incluindo os tempos ociosos de certos processadores
são somadas, a cada unidade de tempo, o número de operações
concorrentes podem estar sendo executadas
Exemplo: soma de n elementos
T(n) e P(n): n/2 processadores executam em O(log n) unidades de
tempo
Custo de O(n log n) em O(log n) unidades de tempo
Usando p < P(n) processadores: O(n log n/p)
–
1a unidade de tempo - n/2 operações (somas em paralelo)
–
2a unidade de tempo - n/4 operações (somas em paralelo)
–
3a unidade de tempo - n/8 operações (somas em paralelo)
..............
–
j-ésima unidade de tempo - n/2j operações
Total de operações: ∑ O(log n) n/2j = O(n)
Reduzindo o número de processadores
Princípio de Brent
“
Qualquer algoritmo paralelo com complexidade de tempo T(n) usando
um número suficientemente grande de processadores e que ainda
consistindo de O(e) operações elementares, pode ser implementado
em p processadores com complexidade de tempo
O(  e/p + T(n))
P ro v a ??
Total de Processadores: p
Total de Operações: e
Unidade
de
Tempo
P1
Pk
P2
Pp
Número
de
Operações
e1
1
2
e2
. . . . . .
3
e3
4
.
e4
.
.
.
.
.
T(n)
Tempo Total
≤ ∑
i
 ei 
 p
 
≤
∑
i
  ei  
   + 1
 p

  
≤
 ei 
 p  + T (n)
 
eT
Outra vez: soma de n elementos
seja um modelo PRAM com p = 2q ≤ n = 2k processadores: P1,..., Pp
seja l = n/p = 2 k - q
Ps é responsável por A[l(s - 1) + 1] , …. , A[ls]
cada elemento é um vértice de uma árvore binária
o número de computações concorrentes corresponde ao número de
vértices em cada nível dividido pelos processadores disponíveis
Análise do Algoritmo
Seja o algoritmo em que n elementos são somados usando p
processadores (Obs.: O algoritmo só considera o trabalho de um dado
processador Ps:
primeiro passo: O(n/p) unidades de tempo
segundo passo?
Soma de n Elementos (JáJá)
Soma_Paralela_Ps ( A, p ){
for j =1 to l do
/* l = n/p */
B(l(s - 1) + j): =A(l(s - 1) + j);
for h = 1 to log n do
if (k - h - q ≥ 0) then
for j = 2k-h-q(s - 1) + 1 to 2k-h-q s do
B(j): = B(2j - 1) + B(2j);
else if (s ≤ 2k-h) then
B(s): = B(2s - 1) + B(2s);
if (s = l) then S: = B(1);
}
Memória compartilhada
32
17
4
7
46
10
15
3
P1
10
21
8
25
2
5
9
12
1
P2
11
0
14
5
6
3
10
P3
2
4
7
11
P4
7
10
9
11
10
5
12
14
17
15
32
46
78
21
25
3
Perguntas:
qual o número de operações?
qual o trabalho?
qual o custo
complexidade?
tipo do PRAM?
teria alguma outra versão com um menor de trabalho ou custo?
qual o número de comunicações?
1 Responda as perguntas considerando as duas versões discutidas na sala de
aula
2 especificar o pseudo-algoritmo da segunda versão discutida.
Pointer Jumping
= (V,E) : árvore direcionada
odg(v) e idg(v): graus de saída e entrada do vértice v ∈ V
∃ um vértice r tal que
T
∀ v ∈ V-{r}, odg(v) = 1, odg(r)=0
∀ v ∈ V-{r}, ∃ um caminho de v a r
O vértice r é dita raíz de T
P o in t e r J u m p in g é uma técnica usada para processamento de dados
armazenados em forma de um conjunto de árvores direcionadas
enraizadas
Pointer Jumping - árvore direcionada
Problema
F: floresta de árvores direcionadas enraizadas
especificação: através de um vetor F de n elementos onde
– F(i) = j se (i,j) ∈ E (é um arco) ⇒ j é o pai ou predecessor imediato de i
– F(i) = i se i é a raíz
Problema: determinar a raíz S(j) da árvore contendo o vértice j
Solução Sequencial - resolve o problema em tempo linear:
identificação das raízes: achar todos os vértics v tal que F(v) = v em
O(n)
reversão dos arcos: pois estamos considerando que se (i,j) ∈ E então j
é pai de i em O(n)
execução de uma busca em profundidade ou largura: nesta busca,
podemos saber a partir da raíz r quem são seus descendentes
Solução Paralela
Um algoritmo eficiente foi proposto, sendo um esquema totalmente
diferente do esquema sequencial
inicialmente: ∀ i ∈ V, S(i) é o pai de i
a técnica p o inte r jum p ing consiste em atualizar o sucessor de cada
vértice pelo sucessor do sucessor
– percorrendo desta maneira, corresponde a cada iteração chegar mais e
mais próximo doa raíz da árvore
– a cada iteração, a distância entre o vértice i e seu sucessor S(i) dobra
– o ponto de parada: quando S(i) é a raíz procurada;
Pointer Jumping
início : S[1] = 2
1o passo: S[1] = 3
2o passo: S[1] = 4
3o passo: S[1] = 5
……..
k-ésimo passo: S[1]
S[2] = 3
S[2] = 4
S[2] = 5
S[2] = 5
S[3] = 4
S[3] = 5
S[3] = 5
S[3] = 5
S[4] = 5
S[4] = 5
S[4] = 5
S[4] = 5
S[5] = 5
S[5] = 5
S[5] = 5
S[5] = 5
= raíz ⇒ d(1, S[1]) = 2k (término do Algoritmo)
Pointer Jumping
1
2
3
4
5
R
Complexidade e Corretude do Algoritmo
como podemos provar que o algoritmo está correto?
simplesmente definimos um algoritmo e o executamos?
– seja h a altura máxima de uma árvore qualquer na floresta de árvores
enraizadas direcionadas
– por indução em h
Temos que analisar tal algoritmo, considerando a altura da maior
ávore dentre as da floresta: domina o tempo de execução do
algoritmo
– cada passo j, definição de distância entre i e S[i]
dj(i,S[j]) = 2dj-1(i,S[i])
– por indução em k: supondo verdade que dk-1(i,S[i]) = 2k-1
Complexidade e Corretude do Algoritmo
– assim, no passo k
dk(i,S[j]) = 2 dk -1(i,S[i]) = 2 * 2k-1
– logo, por definição da distância máxima, tem-se h = 2k e assim, o número
máximo de iterações é k = O(log h)
em cada iteração, o tempo paralelo é O(1). Temos um total de O(log
h) iterações. Ainda, o número de processadores é n
o algoritmo paralelo não tem custo ótimo. Por que?
é um algoritmo CREW PRAM
Soma de Prefixos
si = x1 ⊗ x2 ⊗ …. ⊗ xi
saída: n elementos : s1, s2, …., sn
Aplicações: concatenação de strings, soma, multiplicação, etc
Algoritmo Sequencial
Soma_Prefixos_Sequencial( x){
s1 := x1 ;
Para i = 2, …., n
si = si-1 ⊗ xi ;
}
Complexidade: O(n)
Soma de Prefixos
Definição
Seja X = { x1, x2, …., xn } e uma operação ⊗ binária e
a operação ⊗ é fechada sobre X ou seja, se xi e xj são elementos de X
então xi ⊗ xj também é
a operação ⊗ é associativa
Soma de Prefixos - pointer jumping
representação dos elementos é feita através de uma árvore
direcionada enraizada
– cada vértice i da árvore tem um peso associado xi
– pointer jumping é usado, armazenando as somas intermediárias a
cada iteração
– como várias árvores podem ser percorridas ao mesmo tempo,
várias seqüências podem ser resolvidas ao mesmo tempo
algoritmo para soma de prefixos: temos a informação de quem é pai
do vértice i, ou seja, F[i]
– em seqüência de n elementos F[i] = i+ 1, i = 1,…., n-1
– a árvore seria uma lista linear
Soma de Prefixo – outro paradigma
si = x1 ⊗ x2 ⊗ …. ⊗ xi
saída: n elementos : s1, s2, …., sn
Paradigma: ávores binárias
A[i] = xi
B[h,j] e C[h,j] onde 1 ≤ j ≤ n/2h (1 ≤ h ≤ log n especifica o nível)
ao final: sj = C[0,j]
Algoritmo Paralelo não Recursivo
Soma_Prefixos_Paralela_nRecursivo( A ){
1. Para 1 ≤ i ≤ n faça em // : B[0,j] := A[j];
2. Para 1 ≤ h ≤ log n faça
2.1
Para 1 ≤ j ≤ n/2h faça em //
2.1.1
B[h,j] := B[h - 1, 2j-1] * B[h - 1, 2j];
3. Para h = log n … 0 faça
3.1
Para 1 ≤ j ≤ n/2h faça em //
3.1.1
se j é par, então C[h,j] := C[h + 1,j/2];
3.1.2
se j == 1, então C[h,1] := B[h,1];
3.1.3
se j é ímpar, então C[h,j] := C[h + 1,(j-1)/2] * B[h,j];
}
P1
B[0,1]=X1
P2
B[0,2]=X2
P3
P4
P5
B[0,3]=X3
B[0,4]=X4
B[0,5]=X5
P6
B[0,6]=X6
P7
B[0,7]=X7
P8
B[0,8]=X8
B[1,1]=B[0,1]+B[0,2 B[1,2]=B[0,3]+B[0,4 B[1,3]=B[0,5]+B[0,6 B[1,4]=B[0,7]+B[0,8
]
]
]
]
X1+X2
X3+X4
X5+X6
X7+X8
C[1,3]=C[2,1]+B[1,3
]
C[1,4]=C[2,2]
B[2,1]=B[1,1]+B[1,2 B[2,2]=B[1,3]+B[1,4
]
]
X1+X2+x3+x4
X5+X6+x7+x8
B[3,1]=B[2,1]+B[2,2
]
X1+X2+...+x7+x8
C[3,1]=B[3,1]
X1+X2+...+x7+x8
C[2,1]=B[2,1]
C[2,2]=B[3,1]
X1+X2+x3+x4
X1+X2+...+x7+x8
C[1,1]=B[1,1]
C[1,2]=C[2,1]
X1+X2
X1+X2+X3+X4
C[0,1]=B[0,1]
C[0,2]=C[1,1]
X1
X1+X2
X1+X2+...+X5+X6
C[0,3]=C[1,1]+B[0,3
]
X1+X2+X3
X1+X2+...+X7+X8
C[0,4]=C[1,2]
X1+X2+X3+X4
C[0,5]=C[1,2]+B[0,5
]
X1+X2+X3+X4+X5
C[0,6]=C[1,3]
X1+X2...X5+X6
Soma de Prefixos Não Recursivo
C[0,7]=C[1,3]+B[0,7
]
X1+X2+...+X6+X7
C[0,8]=C[1,4]
X1+X2...X7+X8
Princípio de Brent
tempo de execução do algoritmo // A para P(n) processadores: T(n)
w operações do algoritmo A
tempo paralelo do algoritmo considerando p processadores de acordo
com o princípio de Brent:
Tp(n) = w/p + T
Aplicação do Princípio
necessário saber quantas operações são executadas a cada passo
algoritmo de soma de prefixos com n = 2k - número de passos:
2log n + 2 ⇒ 2k+2
– qual o número de operações?
– qual o custo?
Princípio de Brent
w1,1 : número de operações no passo 1considerando o único loop
w2,m : número de operações executadas no passo 2 na m-ésima iteração
w3,m : número de operações executadas no passo 3 na m-ésima iteração
Então:
w1,1 = n
w2,m = n/2m = 2k /2m para 1 ≤ m ≤ k
w3,m = 2m para 0 ≤ m ≤ k
Assim:
w = w1,1 + ∑ w2,m + ∑ w3,m
w = n + ∑ n/2m + ∑ 2m
w = n + n(1-1/n) + 2n-1 = 4n-2
w = O(n)
Divisão e Conquista
usada quando identificamos problemas que podem ser particionados
em subproblemas menores, que são mais simples de serem resolvidos
– divisão da entrada em partições menores de mesmo tamanho (ou quase)
– resolução recursiva de cada subproblema definido por cada partição
– combinação das soluções de cada subproblema, produzindo a solução do
problema como um todo
tende a ser eficiente se a decisão e resolução podem ser feitas
recursivamente
eficiente no mundo seqüencial
natural na exploração de paralelismo
Divisão e Conquista
Problema da Envoltória Convexa
Seja S = { p1 , p2 , …. , pn } um conjunto de n pontos em um plano, cada um
representado por suas coordenadas (xi, yi). A envoltória convexa planar de S é o
menor polígono convexo que contém todos os pontos de S
observação: um polígono é convexo quando, para qualquer dois pontos,
(xi, yi) ≤ (xj, yj), a reta [(xi, yi),(xj, yj)] está dentro do polígono.
o problema: determinar a lista ordenada de pontos S que formam o
polígono convexo. Essa lista será denotada por CH(S) (convex hull).
Divisão e Conquista
Problema da Envoltória Convexa
é um problema muito importante em geometria planar:
–
–
–
–
–
estatística
processamento de imagem
reconhecimento de padrões
computação gráfica
problemas geométricos
resolvido sequencialmente através de divisão e conquista O(n log n)
– o algoritmo de ordenação de pontos resolve esse problema mais
eficientemente
Divisão e Conquista Paralelo
Dado um conjunto S de n pontos, sejam:
p ∈ S o ponto com o menor xi
q ∈ S o ponto com o maior xj
ordenação paralela: em O(log n) em uma PRAM EREW com O(n log n )
operações
particionam CH(S) em:
envoltório superior UH(S) = < todos os pontos de p a q pertencentes a
CH(S) seguindo o sentido horário >
envoltório inferior LH(S) = < todos os pontos de q a p pertencentes a
CH(S) seguindo o sentido horário >
O Problema da Envoltória Convexa
CH(S)
envoltória superior
UH(S)
S
p
q
envoltória inferior
LH(S)
Divisão e Conquista Paralelo
p
q
Merging de duas envoltórias superiores
p
q
Merging de duas envoltórias superiores
Tangente Comum Superior
• sequencial – O(log n)
• busca binária
p
q
Algoritmo
Entrada: n pontos ordenados tais que x(p1) < x(p2) < .... <
x(pn)
Saída: UH(S)
4)
5)
6)
8)
9)
10)
Se n <= 4 então ache UH(S) por força bruta e retorne
S1 = (p1, ..., pn/2) e S2 = (pn/2+1, pn). Compute UH(S1) e
UH(S2) em paralelo, recursivamente
Ache a tangente comum superior entre UH(S1) e UH(S2) e
defina UH(S)
O(1)
T(n/2)
TCS(UH(S1), UH(S2)) em O (log n)
Combinar as duas curvas dada a tangente produzindo S
– em O(1) com n processadores  leituras concorrentes
serão realizadas.
Algoritmo
Explicar:
– ComplexidadeT(n) = O(log2 n) com O(n) processadores
Qual o número de operações?
Desempenho de computação paralela
o paralelismo existente na aplicação
decomposição do problema em subproblemas menores
a alocação destes subproblemas aos processadores
o modo de acesso aos dados:
– a existência de uma memória global
– ou distribuída  comunicação por trocas de mensagens
a estrutura de interconexão entre os processadores
a velocidade dos processadores, memórias e rede de interconexão.
Em ambientes distribuídos, a meta é de explorar e tirar proveito ao máximo do potencial
computacional, sendo assim questões relacionadas ao gerenciamento de recursos do
sistema muito importante
Escalonamento de Aplicações
Um algoritmo que estabelece como executar um algoritmo paralelo em um
determinado sistema de computadores
Para implementar um escalonador, o problema tem que ser especificado:
– As características da aplicação devem ser especificadas
– As características cruciais do sistema de processadores em questão
devem ser estabelecidas
Modelagem
Representação do problema
Representação do ambiente de solução
Simplificação, sem omitir as características que afetam o desempenho em
geral
Qual o objetivo?
Escalonar aplicações em um sistema paralelo e distribuído tal que o tempo
de execução seja minimizado
Escalonar aplicações em um número limitado de processadores tal que o
tempo de execução seja minimizado, considerando custo de comunicação
Escalonar aplicações em um número limitado de processadores tal que o
tempo de execução seja minimizado considerando tempos limites (deadline),
considerando custo de comunicação
⇓
o objetivo deve estar especificado
Uma Classe de Problemas
Escalonamento de Aplicações em um Sistema de Computadores Distribuídos
classe de aplicações
– especificada pelo modelo da aplicação
a arquitetura enfocada constitui em um sistema de processadores de
memória distribuída que se comunicam por trocas de mensagens
– modelo arquitetural apresenta as características importantes a serem
consideradas
Escalonamento de Aplicações
Alguns conceitos
Tarefa – uma unidade de computação
job = conj. de tarefas com objetivo comum
aplicação paralela  tarefas que seguem
uma ordem parcial
Escalonamento de Aplicações
Escalonamento local X global
global  tarefas são associadas a processadores
 mapeamento, task placement, matching
local  várias tarefas em um processador
No escalonamento global:
- migração – custoso e nem sempre usado (sala contexto, trasfere contexto
para o novo processador, reinicializa tarefa)
- geralmente se refere a balanceamento de carga
Balanceamento de Carga
receiver-initiated
sender-initiated
P1
P2
P1
P2
Mais conceitos
preempção  tarefas/jobs em execução podem ser transferidas (migradas)
– mais custos
não preempção  geralmente em relação às tarefas
– tarefas não são interrompidas
– migração somente para tarefas ainda por executar
Escalonamento de Aplicações
Estático
conhecimento de características associadas às aplicações antes da execução
desta (estimativas)
relação de precedência entre os componentes da aplicação
Dinâmico
estimativas são conhecidas antes da execução e não as características
reais.
a especificação do escalonamento é feita ao longo da execução da
aplicação
– balanceamento de carga, por exemplo
Escalonamento Estático de Aplicações
O Problema de Escalonamento de Tarefas em um conjunto de
processadores é, em sua forma geral, NP-completo.
Uma variedade de heurísticas de escalonamento foram propostas,
principalmente para um conjunto de processadores homogêneos,
considerando ou não custo de comunicação associado à troca de
mensagens
Alguns heurísticas que consideram um conjunto de processadores
homogêneos foram analiticamente avaliadas, e foi concluído que
escalonamento produzidos estão dentro de um fator do ótimo.
Algumas instâncias do problema possuem solução ótima
Modelo da Aplicação
uma aplicação da classe de aplicações abordadas é constituída por um
conjunto de tarefas, ordenadas parcialmente por uma relação de
precedência
a classe de aplicações aqui discutida pode ser representada por um grafo
acíclico direcionado (GAD) G = (V,E, ε, ω), onde
– as tarefas da aplicação são representadas pelo conjunto de n vértices
V = { v1 , v2 , ... , vn }
– as relações de precedência que correspondem a dependência de dados
são representadas pelo conjunto de dados
E = { (vi , vj ) }
Modelo da Aplicação
o peso de computação ε(vi) pode estar associado a cada tarefa de G
(estimativa) correspondendo ao número de unidades de tempo
necessários para executar a tarefa vi
o peso de comunicação ω(vi, vj ) pode estar associado a cada arco (vi, vj )
de G (estimativa) correspondendo à quantidade de dados a serem
enviados da tarefa vi para a vj
seja pred (vi) o conjunto de predecessores imediatos da tarefa vi , ou
seja,
pred (vi) = {vj / (vj ,vi ) ∈ E }
seja succ (vi) o conjunto de sucessores imediatos da tarefa vi , ou seja,
succ (vi) = {vj / (vi , vj ) ∈ E }
Modelo da Arquitetura
definição de características que afetam o desempenho
processadores homogêneos e heterogêneos
número limitado ou não de processadores
memória distribuída ou compartilhada
topologia da rede de interconexão
modelo de comunicação
– latência de comunicação
– sobrecargas de envio e recebimento
– etc
Heurísticas de Escalonamento
Heurísticas de Escalonamento Estático
heurísticas de construção: um algoritmo polinomial no tamanho da
entrada que a cada iteração, especifica para uma tarefa o seu
escalonamento
– tupla (tarefa, processador, tempo de início)
– ao final, uma só solução foi formada
– escalonamento deve ser válido (respeitar as relações de precedência
e as características do modelo arquitetural)
difícil classificação
– técnica empregada
– modelo considerado
Heurísticas de Escalonamento
Heurísticas de Escalonamento Estático
List Scheduling
Algomeração de Tarefas
Minimização de Caminho Crítico
Replicação de Tarefas
List Scheduling
Estratégia (extremamente) gulosa
tradicional e bastante conhecida (utilizada) devido a sua simplicidade
(baixa complexidade)
– escalonamento de instruções em unidades funcionais
– escalonamento em processadores heterogêneos (em número
limitado)
Alguns conceitos importantes
tarefa livre - todos os seus predecessores imediatos já foram
escalonados;
processador ocioso - em um determinado instante tk , não existe
nenhuma tarefa sendo executada neste instante;
List Scheduling Framework
Definição da prioridade das tarefas vi ∈ V;
Enquanto ( existir vi não escalonado ) faça {
vi = a tarefa livre de maior prioridade;
pj = o processador ocioso onde vi começa mais cedo;
escalone vi no processador pj ;
determine as novas tarefas livres;
}
1
pesos de execução em
pesos dos arcos em
4
0
2
8
4
5
1
2
2
3
3
1
4
2
6
5
6
5
4
3
6
7
Um Exemplo de GAD
Custos Unitários
0
2
1
3
4
9
5
6
8
7
11
10
Programação Distribuída
Introdução e Conceitos Básicos
Conceitos Básicos
Sistema Distribuído:
– Não há compartilhamento de memória
– Troca de informação através de troca de mensagens
Programa Distribuído: Conjunto de processos que trabalham em conjunto
para solucionar um problema
Programas Distribuídos são executados em Sistemas Distribuídos
Conceitos Básicos
Áreas de demanda:
– Otimização combinatória
– Mineração de dados
– Simulações
– Meteorologia
– Bioinformática
– Computação gráfica
Computação intensiva !!
Conceitos Básicos
Seqüencial ≠ Distribuído - Determinação de estado não é trivial
Seqüencial
Distribuído
if (x=1) then
if (x proc a = 1) and
(y proc b = 2) then
Não é trivial !!!
Conceitos Básicos
Inst
Inst
...
Inst
...
...
...
...
Inst
1
2
x
y
msg
Inst 1
Inst 2
Inst 3
...
...
Inst z
...
...
Inst w
tempo
tempo
Seqüencial ≠ Distribuído - Ausência de uma base de tempo global
Conceitos Básicos
Distribuído ≠ Centralizado - Não determinístico
P(i)
P(i)
P(j)
P(j)
P(k)
P(k)
Modelos de Computação
Assíncrono:
– Sem coordenação global
– Atraso na transmissão das mensagens é finito mas não determinado
– Desenvolvimento mais complexo
– Realístico
Síncrono:
– Com coordenação global
– Comunicação em “pulsos”
– Desenvolvimento mais simples
– Menos realístico
Modelo utilizado
Um programa paralelo distribuído é representado por um grafo não
orientado G = (N,E) onde:
– N : conjunto de nós que representam processos
– n = |N|
– E : conjunto de arestas que representam canais de comunicação
– e = |E|
Para i = 1, 2, 3, ..., n, pi ∈ N é um processo que pode se comunicar
exclusivamente por troca de mensagens com os processos pj tal que (pi, pj)
∈E
Canais de comunicação bidirecionais de capacidade infinita
Métricas para Avaliação
CORRETUDE
Número/Tamanho das mensagens enviadas
Tempo de convergência:
– Síncrono: Nr. de pulsos
– Assíncrono: Maior cadeia de mensagens com relação de “causalidade”
Introdução ao MPI
Introdução
O MPI é um padrão para desenvolvimento de aplicações distribuídas
Disponível na forma de bibliotecas para linguagens C, C++ e Fortran
SPMD – Single Program Multiple Data – todos os processos executam o
MESMO programa
Síntese de diversos sistemas anteriores
Histórico Breve
Desenvolvido por um fórum aberto internacional composto por
representantes da indústria, universidade e entidades governamentais
Influenciado por outras plataformas e comunidades: Zipcode, Chimp, PVM,
Chamaleon e PICL
Padronização iniciada em abril de 1992
Objetivos
Eficiência na comunicação
Ambientes para desenvolvimento e execução heterogêneos
Fácil aprendizado para atuais programadores de aplicações distribuídas
(interface parecida com a do PVM)
Características
Supõe que a subcamada de comunicação é confiável
Garante ordem de entrega das mensagens
Trabalha com o conceito de COMUNICADORES, que definem o universo de
processos envolvidos em uma operação de comunicação
Cada processo ganha uma identificação numérica (rank)
Comandos de incialização e finalização
MPI_Init : Inicializa o ambiente de execução
MPI_Comm_rank: Determina o rank (identificação) do processo no
comunicador
MPI_Comm_size: Determina o número de processos no comunicador
MPI_Finalize: Termina o ambiente de execução
Comunicação Ponto a Ponto
O que acontece se um processo tentar receber uma mensagem que ainda
não foi enviada?
– Função BLOQUEANTE de recebimento (MPI_Recv) : bloqueia a aplicação
até que o buffer de recepção contenha a mensagem
– Função NÃO BLOQUEANTE de recebimento (MPI_Irecv) : retorna um
handle request, que pode ser testado ou usado para ficar em espera
pela chegada da mensagem
MPI_Send
int MPI_Send(void* message, int count, MPI_Datatype
datatype, int dest, int tag, MPI_Comm comm)
message: endereço inicial da informação a ser enviada
count: número de elementos do tipo especificado a enviar
datatype: MPI_CHAR, MPI_INT, MPI_FLOAT, MPI_BYTE,
MPI_LONG, MPI_UNSIGNED_CHAR, etc
dest: rank do processo destino
tag: identificador do tipo da mensagem
comm: especifica o contexto da comunicação e os processos
participantes do grupo. O padrão é MPI_COMM_WORLD
MPI_Recv
int MPI_Recv(void* message, int count,
MPI_Datatype datatype, int source, int tag,
MPI_Comm comm, MPI_Status* status)
message: Endereço inicial do buffer de recepção
count: Número máximo de elementos a serem recebidos
datatype: MPI_CHAR, MPI_INT, MPI_FLOAT, MPI_BYTE,
MPI_LONG, MPI_UNSIGNED_CHAR, etc.
source: rank do processo origem ( * = MPI_ANY_SOURCE)
tag: tipo de mensagem a receber ( * = MPI_ANY_TAG)
comm: comunicador
status: Estrutura com três campos: MPI_SOURCE_TAG, MPI_TAG,
MPI_ERROR
MPI_Irecv
Menos utilizada
Parâmetros iguais ao bloqueante, acrescido de uma estrutura (request) que
armazena informações que possibilitam o bloqueio posterior do processo
usando a função MPI_Wait(&request, &status)
Comunicação Coletiva
mais restritivas que as comunicações ponto a ponto:
– quantidade de dados enviados deve casar exatamente com a
quantidade de dados especificada pelo receptor
– Apenas a versão bloqueante das funções está disponível
– O argumento tag não existe
Todos os processos participantes da comunicação coletiva
chamam a mesma função com argumentos compatíveis
Algumas Funções para Comunicação Coletiva
MPI_Barrier: Bloqueia o processo até que todos os processos
associados ao comunicador chamem essa função
Inst 1
Inst 2
Inst 3
...
...
MPI_Barrier(comm)
...
...
Inst 1
Inst 2
Inst 3
...
...
MPI_Barrier(comm)
...
...
Inst 1
Inst 2
Inst 3
...
...
MPI_Barrier(comm)
...
...
Algumas Funções para Comunicação Coletiva
MPI_Bcast: Faz a difusão de uma mensagem do processo raiz para
todos os processos associados ao comunicador
P(i)
P(j)
Inst 1
Inst 2
Inst 3
...
...
MPI_Bcast(....)
...
...
msg
P(k)
Algumas Funções para Comunicação Coletiva
MPI_Reduce: Combina todos os elementos presentes no buffer de cada
processo do grupo usando a operação definida como parâmetro e coloca o
valor resultante no buffer do processo especificado. O exemplo abaixo soma
todas as variáveis “x” armazenando o total na variável “tot” do processo 2.
Processo 0
Inst 1
Inst 2
...
x=1;
MPI_Reduce(&x, &tot,
MPI_INT,
MPI_SUM,
2,
comm)
...
...
Processo 1
Inst 1
Inst 2
...
x=10;
MPI_Reduce(&x, &tot,
MPI_INT,
MPI_SUM,
2,
comm)
...
...
Processo 2
Inst 1
Inst 2
...
x=3;
MPI_Reduce(&x, &tot,
MPI_INT,
MPI_SUM,
2,
comm)
...
...
Programa Exemplo (1/3)
#include <stdio.h>
#include <string.h>
#include “mpi.h”
main(int argc, char** argv)
{
int meu_rank, np, origem, destino, tag=0;
char msg[100];
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &meu_rank);
MPI_Comm_size(MPI_COMM_WORLD,&np);
Programa Exemplo (2/3)
if (my_rank != 0) {
sprintf(msg, “Processo %d está vivo!”, meu_rank);
destino = 0;
MPI_Send(msg,
strlen(msg)+1,
MPI_CHAR,
destino,
tag,
MPI_COMM_WORLD);
}
Programa Exemplo (3/3)
else {
// if (my_rank == 0)
for (origem=1; origem<np; origem++) {
MPI_Recv(msg,
100,
MPI_CHAR,
origem,
tag,
MPI_COMM_WORLD,
&status);
printf(“%s\n”,msg);
}
}
MPI_Finalize( );
}
Alguns Algoritmos Distribuídos
•Propagação de Informação
•Propagação com Realimentação
•Integral Definida
•Conectividade em Grafos
•Distância Mínima
Grafo para testes
0
1
3
2
4
5
int matrizVizinhanca[6][6] = {
{0,1,1,0,0,0},
{1,0,1,1,1,0},
{1,1,0,0,0,1},
{0,1,0,0,0,0},
{0,1,0,0,0,0},
{0,0,1,0,0,0}
};
Propagação de Informações
Propagação de Informações
0
1
3
Nó 0 gera uma informação que
tem de ser encaminhada a todos
os demais.
2
4
5
Propagação de Informações - Algoritmo
Variáveis:
alcançado = falso
Ação para fonte inicial da informação (inf):
alcançado := verdadeiro;
envie inf a todos os vizinhos;
Ao receber inf
se alcançado = falso;
alcançado := verdadeiro;
envie inf a todos os vizinhos;
Propagação de Informações - Execução
0
1
3
Nó 0 gera uma informação e a
encaminha a todos os seus
vizinhos
2
4
5
Propagação de Informações - Execução
0
1
3
Nós 1 e 2 recebem a informação
e a encaminham a todos os seus
vizinhos
2
4
5
Propagação de Informações - Execução
0
1
3
Nós 3, 4 e 5 recebem a
informação e a encaminham a
todos os seus vizinhos
2
4
5
Propagação de Informações
Será possível aumentar a eficiência do algoritmo?
Será necessária a propagação para TODOS os vizinhos?
Inclusive o remetente da mensagem?
Considere outra possível execução, representada nas próximas telas…
Propagação de Informações - Execução
0
1
3
Nó 0 gera uma informação e a
encaminha a todos os seus
vizinhos
2
4
5
Propagação de Informações - Execução
0
1
3
2
4
5
Nós 1 recebe a informação e a
encaminha a todos os seus
vizinhos mas canal de
comunicação 0 - 2 está muito
lento, e 2 recebe a informação de
1 antes de 0
Propagação de Informação - Complexidades
Mensagens: 2e => O(e)
Tempo: n-1 => O(n)
1
2
3
n
Propagação de Informação - Implementação
#include <stdio.h>
#include <mpi.h>
/*Definir o grafo da aplicação antes de executar*/
int numeroDeTarefas = 6;
int matrizVizinhanca[6][6] = {
{0,1,1,0,0,0},
{1,0,1,1,1,0},
{1,1,0,0,0,1},
{0,1,0,0,0,0},
{0,1,0,0,0,0},
{0,0,1,0,0,0}
};
Propagação de Informação - Implementação
/*retorna o número de vizinhos da tarefa myRank*/
int contaNumeroDeVizinhos(int myRank)
{
int i;
int contador = 0;
for (i = 0; i < numeroDeTarefas; i++)
if (matrizVizinhanca[myRank][i] == 1)
contador++;
return contador;
}
Propagação de Informação - Implementação
/*programa principal*/
int main(int argc, char** argv)
{
int i;
int numeroDeVizinhos;
int myRank;
int source;
int tag = 50;
char message[100] = "Oi!";
MPI_Status status;
//inicialização do MPI
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &myRank);
numeroDeVizinhos = contaNumeroDeVizinhos(myRank);
Propagação de Informação - Implementação
if (myRank == 0)
{
/*enviando para todos os vizinhos de myRank*/
for (i = 0; i < numeroDeTarefas; i++)
if (matrizVizinhanca[myRank][i] == 1)
{
printf("Enviando mensagem para %d\n", i);
MPI_Send(message, strlen(message)+1, MPI_CHAR, i,
tag,
MPI_COMM_WORLD);
}
/*recebendo de todos os vizinhos de myRank*/
for(i = 0; i < numeroDeVizinhos; i++)
{
MPI_Recv(message, 100, MPI_CHAR, MPI_ANY_SOURCE, tag,
MPI_COMM_WORLD, &status);
printf("Recebendo msg de %d\n", status.MPI_SOURCE);
}
}
Propagação de Informação - Implementação
else
{
/*recebendo msg de uma tarefa vizinha qualquer*/
MPI_Recv(message, 100, MPI_CHAR, MPI_ANY_SOURCE, tag,
MPI_COMM_WORLD, &status);
/*enviando para todos os vizinhos de myRank*/
for (i = 0; i < numeroDeTarefas; i++)
if (matrizVizinhanca[myRank][i] == 1)
MPI_Send(message, strlen(message)+1, MPI_CHAR, i, tag,
MPI_COMM_WORLD);
/*recebendo de todos os vizinhos de myRank menos 1*/
for(i = 0; i < (numeroDeVizinhos - 1); i++)
MPI_Recv(message, 100, MPI_CHAR, MPI_ANY_SOURCE, tag,
MPI_COMM_WORLD, &status);
}
// Finalização do MPI
MPI_Finalize();
}
Propagação de Informações com Realimentação
Propagação de Informações com Realimentação
0
1
3
2
4
5
Nó 0 gera uma informação que
tem de ser encaminhada a todos
os demais e recebe uma
confirmação quando a informação
já estiver completamente
disseminada.
Propagação de Informações com Realimentação - Algoritmo
Variáveis
pai := nil;
count := 0;
alcançado := falso;
Ação para fonte inicial da informação (inf):
alcançado := verdadeiro;
envie inf a todos os vizinhos;
Ao receber inf:
count := count +1;
se alcançado = falso
alcançado := verdadeiro;
pai := origem(inf);
envie inf a todos os vizinhos exceto pai;
se count := |vizinhos| e pai ≠ nil
envie inf para pai;
Propagação de Informações com Realimentação - Execução
0
1
3
Nó 0 gera uma informação e a
encaminha a todos os seus
vizinhos
2
4
5
Propagação de Informações com Realimentação - Execução
0
1
3
Nós 1 e 2 recebem a informação
e a encaminham a todos os seus
vizinhos, exceto pai
2
4
5
Propagação de Informações com Realimentação - Execução
0
1
3
Nós 3, 4 e 5 recebem a
informação e como são folhas, a
retornam para seus pais.
2
4
5
Propagação de Informações com Realimentação - Execução
0
1
3
Nós 1 e 2 receberam o retorno de
seus filhos e podem informar ao
seus pais
2
4
5
Propagação de Informações com Realimentação - Execução
0
1
3
2
4
5
Nó 0 recebeu o retorno de todos
os seus filhos e pode concluir
que todos os nós do sistema já
receberam a informação.
Propagação de Informações com Realimentação - Complexidade
Mensagens: 2e => O(e)
Tempo: 2(n-1) => O(n)
1
2
3
n
Propagação de Informações com Realimentação - Implementação
#include <stdio.h>
#include <mpi.h>
/*Definir o grafo da aplicação antes de executar*/
int numeroDeTarefas = 6;
int matrizVizinhanca[6][6] = {
{0,1,1,0,0,0},
{1,0,1,1,1,0},
{1,1,0,0,0,1},
{0,1,0,0,0,0},
{0,1,0,0,0,0},
{0,0,1,0,0,0}
};
Propagação de Informações com Realimentação - Implementação
/*retorna o número de vizinhos da tarefa myRank*/
int contaNumeroDeVizinhos(int myRank)
{
int i;
int contador = 0;
for (i = 0; i < numeroDeTarefas; i++)
if (matrizVizinhanca[myRank][i] == 1)
contador++;
return contador;
}
Propagação de Informações com Realimentação - Implementação
/*programa principal*/
int main(int argc, char** argv)
{
int i;
int numeroDeVizinhos;
int myRank;
int source;
int tag = 50;
int pai;
char message[100] = "Oi!";
MPI_Status status;
//inicialização do MPI
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &myRank);
numeroDeVizinhos = contaNumeroDeVizinhos(myRank);
Propagação de Informações com Realimentação - Implementação
if (myRank == 0)
{
/*enviando para todos os vizinhos de myRank*/
for (i = 0; i < numeroDeTarefas; i++)
if (matrizVizinhanca[myRank][i] == 1)
{
printf("Enviando mensagem para %d\n", i);
MPI_Send(message, strlen(message)+1, MPI_CHAR, i,
tag,
MPI_COMM_WORLD);
}
/*recebendo de todos os vizinhos de myRank*/
for(i = 0; i < numeroDeVizinhos; i++)
{
MPI_Recv(message, 100, MPI_CHAR, MPI_ANY_SOURCE, tag,
MPI_COMM_WORLD, &status);
printf(“Confirmação do filho %d\n", status.MPI_SOURCE);
}
}
Propagação de Informações com Realimentação - Implementação
else
{
/*recebendo msg de uma tarefa vizinha qualquer*/
MPI_Recv(message, 100, MPI_CHAR, MPI_ANY_SOURCE, tag,
MPI_COMM_WORLD, &status);
pai = status.MPI_SOURCE;
/*enviando para todos os vizinhos de myRank menos seu pai*/
for (i = 0; i < numeroDeTarefas; i++)
if ( (matrizVizinhanca[myRank][i] == 1) && (i != pai) )
MPI_Send(message, strlen(message)+1, MPI_CHAR, i, tag,
MPI_COMM_WORLD);
/*recebendo de todos os vizinhos de myRank menos 1*/
for(i = 0; i < (numeroDeVizinhos - 1); i++)
MPI_Recv(message, 100, MPI_CHAR, MPI_ANY_SOURCE, tag,
MPI_COMM_WORLD, &status);
MPI_Send(message, strlen(message)+1, MPI_CHAR, pai, tag,
MPI_COMM_WORLD);
}
Propagação de Informações com Realimentação - Implementação
//Finalização do MPI
MPI_Finalize();
}
Integral Definida
Método do Trapezóide
Integral Definida
y
f(x)
∫ f(x) dx
a
b
a
b
x
Integral Definida – Método do Trapezóide
y
b1=f( x i-1 )
Área do trapézio = h (b1+b2) / 2
b2=f(x i )
f(x)
h=(b-a)/n (constante)
Área do i-ésimo trapésio:
(h/2)[ f(xi-1) + f(xi) ]
a
xi-1 xi
b
x
∫ f(x) dx =
a
b
(h/2)[f(x0)+f(x1) ] + (h/2)[f(x1)+f(x2) ] + (h/2)[f(x2)+f(x3)] + ... + (h/2)[f(xn-1)+f(xn)] =
(h/2)[ f(x0) + 2 f(x1) + 2 f(x2) + 2 f(x3) + ... + 2 f(xn-1) + f(xn) ] =
h [ f(x0)/2 + f(xn)/2 + f(x1) + f(x2) + f(x3) + ... + f(xn-1) ]
supondo:
nrProcessos=3
nrTrapézios=6
=>local_n=2
Integral Definida - Algoritmo
h
f(x)
local_b(2)
local_b(1)=local_a(2)
x
local_b(0)=local_a(1)
Ação inicial para todos os nós:
x := local_a;
integral :=(f(local_a)+f(local_b))/2.0;
para i variando de 1 até local_n-1 faça
x := x + h;
integral := integral + f(x);
integral := integral * h;
y
local_a(0)
Variáveis:
h := (b-a)/nrTrapézios;
local_n := nrTrapézios / nrProcessos;
local_a := a + my_rank * local_n * h;
local_b := local_a + local_n * h;
Integral Definida - Algoritmo
se my_rank = 0
total := integral;
para i variando de 1 até nrProcessos – 1
receba valor na variável integral;
total = total + integral;
imprima “Valor calculado: “ + total;
senão
envie integral para nó 0;
Integral Definida - Implementação
#include <stdio.h>
#include <mpi.h>
main(int argc, char** argv) {
int my_rank;
int p;
// número de processos
float a=0.0, b=1.0; // intervalo a calcular
int n=1024;
// número de trapezóides
float h;
// base do trapezóide
float local_a, local_b;
// intervalo local
int local_n;
// número de trapezóides local
float integral;
// integral no meu intervalo
float total;
// integral total
int source;
// remetente da integral
int dest=0;
// destino das integrais (nó 0)
int tag=200;
// tipo de mensagem (único)
MPI_Status status;
Integral Definida - Implementação
float calcula(float local_a, float local_b,
int local_n, float h);
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
MPI_Comm_size(MPI_COMM_WORLD, &p);
h = (b-a)
local_n =
local_a =
local_b =
/ n;
n / p;
a + my_rank * local_n * h;
local_a + local_n * h;
integral = calcula(local_a, local_b, local_n, h);
Integral Definida - Implementação
if(my_rank == 0) {
total = integral;
for(source=1; source<p; source++) {
MPI_Recv(&integral, 1, MPI_FLOAT, source, tag,
MPI_COMM_WORLD, &status);
total +=integral;
}
} else
MPI_Send(&integral, 1, MPI_FLOAT, dest,
tag, MPI_COMM_WORLD);
if(my_rank == 0) printf(“Resultado: %f\n”, total);
MPI_Finalize();
}
Integral Definida - Implementação
float calcula(float local_a, float local_b,
int local_n, float h) {
float integral;
float x, i;
float f(float x);
// função a integrar
integral = ( f(local_a) + f(local_b) ) /2.0;
x = local_a;
for( i=1; i<=local_n-1; i++) {
x += h;
integral += f(x);
}
integral *= h;
return integral;
}
Integral Definida – Implementação
float f(float x) {
float fx; //
valor de retorno
// esta é a função a integrar
// exemplo: função quadrática
fx = x * x;
return fx;
}
Conectividade em Grafos
Conectividade em Grafos
1,2,3,4,5
0
0,2,3,4,5
1
2
0,1,3,4,5
3
0,1,2,4,5
4
0,1,2,3,5
5
0,1,2,3,4
O problema trata da descoberta, por cada nó, das
identificações de todos os
outros nós aos quais está
conectado.
Conectividade em Grafos - Algoritmo
Variáveis:
initiate = false;
para todos os nós k de N;
parent(k) := nil;
count(k) := 0;
reached(k) := false;
Ação se n ∈ N(0):
initiate := true;
reached(id) := true;
envie id para todos os vizinhos;
Conectividade em Grafos - Algoritmo
Input: id(k) recebido do nó j
se initiated = false
initiated := true;
reached(id) := true;
envie id para todos os vizinhos;
Conectividade em Grafos - Algoritmo
count(k) := count(k) + 1;
se reached(k) = false
reached(k) := true;
parent(k) := j;
para todos os vizinhos exceto parent(k)
envie id(k);
se count(k) = nr de vizinhos de i
se parent(k) ≠ nil
envie id(k) para parent(k)
Conectividade em Grafos - Execução
nó
pare
nt
cou
nt
reach
ed
0
nil
0
False
1
nil
0
False
2
nil
0
3
nil
4
5
3
0
nó
pare
nt
cou
nt
reach
ed
0
nil
0
False
1
nil
0
False
2
nil
0
False
3
nil
0
False
4
nil
0
False
5
nil
0
False
nó
pare
nt
cou
nt
reach
ed
False
0
nil
0
False
0
False
1
nil
0
False
nil
0
False
2
nil
0
False
nil
0
False
3
nil
0
False
4
nil
0
False
5
nil
0
False
2
1
nó
pare
nt
cou
nt
reach
ed
nó
pare
nt
cou
nt
reach
ed
nó
pare
nt
cou
nt
reach
ed
0
nil
0
False
0
nil
0
False
0
nil
0
False
1
nil
0
False
1
nil
0
False
1
nil
0
False
2
nil
0
False
2
nil
0
False
2
nil
0
False
3
nil
0
False
3
nil
0
False
3
nil
0
False
4
nil
0
False
4
nil
0
False
4
nil
0
False
5
nil
0
False
5
nil
0
False
5
nil
0
False
4
5
Conectividade em Grafos - Execução
nó
pare
nt
cou
nt
reach
ed
0
nil
0
False
1
nil
0
True
2
nil
0
False
3
nil
0
False
4
nil
0
False
5
nil
0
False
0
0
3
pare
nt
cou
nt
reach
ed
0
nil
0
True
1
nil
0
False
2
nil
0
False
3
nil
0
False
4
nil
0
False
5
nil
0
False
0
1
2
1
2
2
1
1
1
3
nó
2
nó
pare
nt
cou
nt
reach
ed
0
nil
0
False
1
nil
0
False
2
nil
0
False
3
nil
0
4
nil
5
nil
nó
pare
nt
cou
nt
reach
ed
0
nil
0
False
1
nil
0
False
2
nil
0
True
3
nil
0
False
4
nil
0
False
5
nil
0
False
nó
pare
nt
cou
nt
reach
ed
0
nil
0
False
1
nil
0
False
2
nil
0
False
nó
pare
nt
cou
nt
reach
ed
0
nil
0
False
1
nil
0
False
2
nil
0
False
True
3
nil
0
False
3
nil
0
False
0
False
4
nil
0
True
4
nil
0
False
0
False
5
nil
0
False
5
nil
0
True
4
4
5
5
Conectividade em Grafos - Execução
nó
pare
nt
cou
nt
reach
ed
0
0
1
True
1
nil
0
True
2
2
1
True
3
3
1
True
4
4
1
True
5
nil
0
False
0
2
3
pare
nt
cou
nt
reach
ed
0
nil
0
True
1
1
1
True
2
2
1
True
3
nil
0
False
4
nil
0
False
5
nil
0
False
1
2,3,4
1,5
0,5
0,3,4
2
1
0,2,3
0,2,4
1
nó
nó
pare
nt
cou
nt
reach
ed
0
nil
0
False
1
1
1
True
2
nil
0
False
3
nil
0
4
nil
5
nil
0,1
nó
pare
nt
cou
nt
reach
ed
0
0
1
True
1
1
1
True
2
nil
0
True
3
nil
0
False
4
nil
0
False
5
5
1
True
nó
pare
nt
cou
nt
reach
ed
0
nil
0
False
1
nil
0
False
2
2
1
True
nó
pare
nt
cou
nt
reach
ed
0
nil
0
False
1
1
1
True
2
nil
0
False
True
3
nil
0
False
3
nil
0
False
0
False
4
nil
0
True
4
nil
0
False
0
False
5
nil
0
False
5
nil
0
True
1
4
2
5
Conectividade em Grafos - Execução
nó
pare
nt
cou
nt
reach
ed
0
0
2
True
1
nil
2
True
2
2
2
True
3
3
1
True
4
4
1
True
5
2
1
True
0
1,5
3
pare
nt
cou
nt
reach
ed
0
nil
0
True
1
1
2
True
2
2
2
True
3
1
1
True
4
1
1
True
5
2
1
True
2,3,4
5
3,4
2
1
5
0,2,4
nó
5
nó
pare
nt
cou
nt
reach
ed
0
1
1
True
1
1
1
True
2
1
1
True
3
nil
0
4
1
5
nil
3,4
nó
pare
nt
cou
nt
reach
ed
0
0
2
True
1
1
2
True
2
nil
1
True
3
1
1
True
4
1
1
True
5
5
1
True
nó
pare
nt
cou
nt
reach
ed
0
2
1
True
1
2
1
True
2
2
1
True
nó
pare
nt
cou
nt
reach
ed
0
1
1
True
1
1
1
True
2
1
1
True
True
3
1
1
True
3
nil
0
False
1
True
4
nil
0
True
4
nil
0
False
0
False
5
nil
0
False
5
nil
0
True
0,2,3
4
0,1
5
Conectividade em Grafos - Execução
nó
pare
nt
cou
nt
reach
ed
0
0
4
True
1
nil
3
True
2
2
4
True
3
3
2
True
4
4
2
True
5
2
2
True
5
3
0
3,4
nó
pare
nt
cou
nt
reach
ed
0
nil
0
True
1
1
2
True
2
2
2
True
3
1
2
True
4
1
2
True
5
2
2
True
5
0
0
2
1
2
1
nó
pare
nt
cou
nt
reach
ed
0
1
1
True
1
1
1
True
2
1
1
True
3
nil
0
4
1
5
1
nó
pare
nt
cou
nt
reach
ed
0
0
3
True
1
1
3
True
2
nil
2
True
3
1
2
True
4
1
2
True
5
5
1
True
nó
pare
nt
cou
nt
reach
ed
0
2
1
True
1
2
1
True
2
2
1
True
nó
pare
nt
cou
nt
reach
ed
0
1
1
True
1
1
1
True
2
1
1
True
True
3
1
1
True
3
2
1
True
1
True
4
nil
0
True
4
2
1
True
1
True
5
1
1
True
5
nil
0
True
5
4
3,4
5
Conectividade em Grafos - Execução
nó
pare
nt
cou
nt
reach
ed
0
0
4
True
1
nil
4
True
2
2
4
True
3
3
3
True
4
4
3
True
5
2
4
True
3
0
nó
pare
nt
cou
nt
reach
ed
0
nil
2
True
1
1
2
True
2
2
2
True
3
1
2
True
4
1
2
True
5
2
2
True
5
3,4
2
1
nó
pare
nt
cou
nt
reach
ed
0
0
3
True
1
1
3
True
2
nil
3
True
3
1
3
True
4
1
3
True
5
5
2
True
nó
pare
nt
cou
nt
reach
ed
nó
pare
nt
cou
nt
reach
ed
nó
pare
nt
cou
nt
reach
ed
0
1
1
True
0
1
1
True
0
2
1
True
1
1
1
True
1
1
1
True
1
2
1
True
2
1
1
True
2
1
1
True
2
2
1
True
3
nil
0
True
3
1
1
True
3
2
1
True
4
1
1
True
4
nil
0
True
4
2
1
True
5
1
1
True
5
1
1
True
5
nil
0
True
4
5
Conectividade em Grafos - Execução
nó
pare
nt
cou
nt
reach
ed
0
0
4
True
1
nil
4
True
2
2
4
3
3
4
5
0
pare
nt
cou
nt
reach
ed
0
nil
2
True
1
1
2
True
2
2
2
True
3
1
2
True
4
1
2
True
5
2
2
True
nó
pare
nt
cou
nt
reach
ed
True
0
0
3
True
4
True
1
1
3
True
4
4
True
2
nil
3
True
2
4
True
3
1
3
True
4
1
3
True
5
5
3
True
2
1
3
3
nó
4
5
nó
pare
nt
cou
nt
reach
ed
nó
pare
nt
cou
nt
reach
ed
nó
pare
nt
cou
nt
reach
ed
0
1
1
True
0
1
1
True
0
2
1
True
1
1
1
True
1
1
1
True
1
2
1
True
2
1
1
True
2
1
1
True
2
2
1
True
3
nil
0
True
3
1
1
True
3
2
1
True
4
1
1
True
4
nil
0
True
4
2
1
True
5
1
1
True
5
1
1
True
5
nil
0
True
4
5
Conectividade em Grafos - Execução
nó
pare
nt
cou
nt
reach
ed
0
0
4
True
1
nil
4
True
2
2
4
3
3
4
5
3
0
nó
pare
nt
cou
nt
reach
ed
0
nil
2
True
1
1
2
True
2
2
2
True
3
1
2
True
4
1
2
True
5
2
2
True
nó
pare
nt
cou
nt
reach
ed
True
0
0
3
True
4
True
1
1
3
True
4
4
True
2
nil
3
True
2
4
True
3
1
3
True
4
1
3
True
5
5
3
True
2
1
nó
pare
nt
cou
nt
reach
ed
nó
pare
nt
cou
nt
reach
ed
nó
pare
nt
cou
nt
reach
ed
0
1
1
True
0
1
1
True
0
2
1
True
1
1
1
True
1
1
1
True
1
2
1
True
2
1
1
True
2
1
1
True
2
2
1
True
3
nil
1
True
3
1
1
True
3
2
1
True
4
1
1
True
4
nil
1
True
4
2
1
True
5
1
1
True
5
1
1
True
5
nil
1
True
4
5
Conectividade em Grafos – Implementação
#include <stdio.h>
#include <mpi.h>
int numeroDeTarefas = 8;
int matrizVizinhanca[8][8] = {
};
{0,1,1,0,0,0,0,0},
{1,0,1,1,1,0,0,0},
{1,1,0,0,0,0,0,0},
{0,1,0,0,0,0,0,0},
{0,1,0,0,0,0,0,0},
{0,0,0,0,0,0,1,1},
{0,0,0,0,0,1,0,1},
{0,0,0,0,0,1,1,0},
Conectividade em Grafos – Implementação
/*retorna o número de vizinhos da tarefa myRank*/
int contaNumeroDeVizinhos(int myRank)
{
int i;
int contador = 0;
for (i = 0; i < numeroDeTarefas; i++)
if (matrizVizinhanca[myRank][i] == 1)
contador++;
return contador;
}
Conectividade em Grafos – Implementação
int finaliza(int contador[], int numeroDeVizinhos,
int myRank) {
int i, todosiguaisa0=1;
if(contador[myRank]!=numeroDeVizinhos) return 0;
else return 1;
}
Conectividade em Grafos – Implementação
/*programa principal*/
int main(int argc, char** argv)
{
int i, j;
int numeroDeVizinhos;
int myRank;
int source;
int tag = 50;
int pai[numeroDeTarefas];
int contador[numeroDeTarefas];
int reached[numeroDeTarefas];
int id;
int origem;
MPI_Status status;
Conectividade em Grafos – Implementação
//inicialização do MPI
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &myRank);
numeroDeVizinhos = contaNumeroDeVizinhos(myRank);
//inicializando variáveis
for (i=0; i<numeroDeTarefas; i++)
{
pai[i]=-1;
contador[i]=0;
reached[i]=0;
}
reached[myRank]=1;
Conectividade em Grafos – Implementação
//enviando minha id para os vizinhos
for (i=0; i<numeroDeTarefas; i++)
{
if (matrizVizinhanca[myRank][i]==1)
MPI_Send(&myRank, 1, MPI_INT, i, tag,
MPI_COMM_WORLD);
}
Conectividade em Grafos – Implementação
while (!finaliza(contador, numeroDeVizinhos, myRank))
{
MPI_Recv(&id, 1, MPI_INT, MPI_ANY_SOURCE, tag,
MPI_COMM_WORLD, &status);
origem=status.MPI_SOURCE;
contador[id]++;
if (reached[id]==0) {
reached[id]=1;
pai[id]=origem;
for (j=0; j<numeroDeTarefas; j++)
if (matrizVizinhanca[myRank][j]==1 && j!=pai[id])
MPI_Send(&id, 1, MPI_INT, j, tag,
MPI_COMM_WORLD);
}
Conectividade em Grafos – Implementação
if (contador[id]==numeroDeVizinhos)
if (pai[id]!=-1)
MPI_Send(&id, 1, MPI_INT, pai[id], tag,
MPI_COMM_WORLD);
}
//imprimindo resultado
printf("processo %d: Elementos conectados: ", myRank);
for (i=0; i<numeroDeTarefas; i++)
if (contador[i]!=0) printf("%d ", i);
printf("\n");
fflush(stdout);
//Finalização do MPI
MPI_Finalize();
}
Distância Mínima
Algoritmo Síncrono
Algoritmo Assíncrono
Distância Mínima
nó
dist.
first
nó
dist.
first
1
1
1
0
1
0
2
1
2
2
1
2
3
2
1
3
1
3
4
2
1
4
1
4
5
2
2
5
2
2
0
1
3
Ao final do algoritmo, cada
nó deve conhecer a
distância mais curta para
cada um dos demais, e
através de qual vizinho se
atinge outro nó com esta
distância.
2
4
5
nó
dist.
first
0
2
2
1
2
2
2
3
2
3
3
2
4
3
2
Por exemplo, estas são
as informações dos nós
0, 1 e 5.
Distância Mínima – Algoritmo Síncrono
Variáveis:
dist(i) := 0;
dist(k) := n para todo nó k ≠ i;
first(k) = nil para todo nó k ≠ i;
set = {id};
Inicio: s=0, msg(0)={}
se n ∈ N(0):
envie set para todos os vizinhos
Distância Mínima – Algoritmo Síncrono
Entrada:
0<s≤n-1,
msg(s) com set`s recebidos de nós n(j);
set := {};
para cada set recebido em msg
para cada id(k) em set
se dist(k)>s
dist(k) := s;
first(k) := n(j);
set := set U {id(k)}
envie set para todos os vizinhos
Distância Mínima – Algoritmo Assíncrono
Variáveis:
dist(i) := 0;
dist(k) := n para todo nó k ≠ i;
first(k) := nil para todo nó k ≠ i;
set := {id};
level(j) := 0 para todos os vizinhos de i;
state := 0;
initiate := false;
Ação se n ∈ N(0):
initiate := true;
envie set para todos os vizinhos;
Distância Mínima – Algoritmo Assíncrono
Input: set(j);
Se initiate = false
initiate := true;
envie set para todos os vizinhos;
se state < n-1
level(j) := state + 1;
para cada id(k) em set
se dist(k) > level(j)
dist(k) := level(j);
first(k) := n(j);
Distância Mínima – Algoritmo Assíncrono
se state < level(j) para todo j vizinho
state := state + 1;
set := {id(k) | dist(k) = state};
envie set para todos os vizinhos;
State=0
Distância Mínima – Execução
State=0
nó
First
Dist
Level
0
nil
6
-1
1
nil
6
---
2
nil
6
-1
3
nil
6
-1
4
nil
6
-1
5
nil
6
---
0
0
3
0
3
nil
Dist
Level
0
nil
6
---
1
nil
6
-1
2
nil
6
-1
3
nil
6
---
4
nil
6
---
5
nil
6
---
0
2
1
2
2
1
1
2
State=0
First
First
1
1
nó
nó
State=0
Dist
6
Level
---
1
nil
6
-1
2
nil
6
---
3
nil
6
---
4
nil
6
---
5
nil
6
---
4
4
State=0
nó
First
Dist
Level
0
nil
6
-1
1
nil
6
-1
2
nil
6
---
3
nil
6
---
4
nil
6
---
5
nil
6
-1
State=0
nó
First
Dist
Level
nó
First
Dist
Level
0
nil
6
---
0
nil
6
---
1
nil
6
-1
1
nil
6
---
2
nil
6
---
2
nil
6
-1
3
nil
6
---
3
nil
6
---
4
nil
6
---
4
nil
6
---
5
nil
6
---
5
nil
6
---
5
5
State=1
Distância Mínima – Execução
State=1
nó
First
Dist
Level
0
0
1
0
1
Nil
6
---
2
2
1
0
3
3
1
0
4
4
1
0
5
nil
6
---
0
2
1
3
0
nil
Dist
Level
0
nil
6
---
1
1
1
0
2
2
1
0
3
nil
6
---
4
nil
6
---
5
nil
6
---
1
1,5
0,5
0,3,4
2
1
0,2,3
0,1
State=1
First
First
2,3,4
0,2,4
nó
nó
State=1
Dist
6
Level
---
1
1
1
0
2
nil
6
---
3
nil
6
---
4
nil
6
---
5
nil
6
---
1
4
State=1
nó
First
Dist
Level
0
0
1
0
1
1
1
0
2
nil
6
---
3
nil
6
---
4
nil
6
---
5
5
1
0
State=1
nó
First
Dist
Level
nó
First
Dist
Level
0
nil
6
---
0
nil
6
---
1
1
1
0
1
nil
6
---
2
nil
6
---
2
2
1
0
3
nil
6
---
3
nil
6
---
4
nil
6
---
4
nil
6
---
5
nil
6
---
5
nil
6
---
2
5
State=2
Conectividade em Grafos - Execução
State=2
nó
First
Dist
Level
0
0
1
1
1
Nil
6
---
2
2
1
1
3
3
1
1
4
4
1
1
5
2
2
---
0
1,5
0,2,4
3
Dist
Level
0
nil
6
---
1
1
1
1
2
2
1
1
3
1
2
---
4
1
2
---
5
2
2
---
2,3,4
3,4
2
1
5
3,4
State=2
First
First
5
5
nó
nó
State=2
Dist
Level
0
1
2
---
1
1
2
1
2
1
6
---
3
nil
6
---
4
1
2
---
5
nil
6
---
0,2,3
4
State=2
nó
First
Dist
Level
0
0
6
1
1
1
6
1
2
2
6
---
3
1
2
---
4
1
2
---
5
5
6
1
State=2
nó
First
Dist
Level
nó
First
Dist
Level
0
1
2
---
0
2
2
---
1
1
1
1
1
2
2
---
2
1
2
---
2
2
1
1
3
1
2
---
3
nil
6
---
4
nil
6
---
4
nil
6
---
5
nil
6
---
5
nil
6
---
0,1
5
State=3
Conectividade em Grafos - Execução
State=3
nó
First
Dist
Level
0
0
1
2
1
Nil
6
---
2
2
1
2
3
3
1
2
4
4
1
2
5
2
2
---
0
First
Dist
Level
0
nil
6
---
1
1
1
2
2
2
1
2
3
1
3
---
4
1
3
---
5
2
3
---
Algoritmo prossegue trocando
mensagens vazias enquanto
state<n-1
2
1
State=3
3
nó
State=3
nó
First
Dist
Level
0
1
2
---
1
1
2
2
2
1
6
---
3
nil
6
---
4
1
2
---
5
nil
6
---
4
State=3
nó
First
Dist
Level
0
0
6
2
1
1
6
2
2
2
6
---
3
1
2
---
4
1
2
---
5
5
6
2
State=3
nó
First
Dist
Level
nó
First
Dist
Level
0
1
2
---
0
2
2
---
1
1
1
2
1
2
2
---
2
1
2
---
2
2
1
2
3
1
2
---
3
nil
6
---
4
nil
6
---
4
nil
6
---
5
nil
6
---
5
nil
6
---
5
Distância Mínima – Implementação
#include <stdio.h>
#include <mpi.h>
/*Definir o grafo da aplicação antes de executar*/
int numeroDeTarefas = 6;
int matrizVizinhanca[6][6] = {
{0,1,1,0,0,0},
{1,0,1,1,1,0},
{1,1,0,0,0,1},
{0,1,0,0,0,0},
{0,1,0,0,0,0},
{0,0,1,0,0,0}
};
Distância Mínima – Implementação
/*retorna o número de vizinhos da tarefa myRank*/
int contaNumeroDeVizinhos(int myRank)
{
int i;
int contador = 0;
for (i = 0; i < numeroDeTarefas; i++)
if (matrizVizinhanca[myRank][i] == 1)
contador++;
return contador;
}
Distância Mínima – Implementação
/*programa principal*/
int main(int argc, char* argv[])
{
int i, j, contador;
int numeroDeVizinhos;
int myRank;
int source;
int tag=50;
int pai;
MPI_Status status;
int origem;
int state;//marca o pulso atual deste processo
int dist[numeroDeTarefas];//distância
int first[numeroDeTarefas];//primeiro nó no caminho
int set[numeroDeTarefas];
int level[numeroDeTarefas];//pulso dos meus vizinhos
Distância Mínima – Implementação
//inicialização do MPI
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &myRank);
numeroDeVizinhos = contaNumeroDeVizinhos(myRank);
printf("iniciando...\n");
fflush(stdout);
//inicializando vetor dist e first
for (i=0; i<numeroDeTarefas; i++)
{
dist[i]=numeroDeTarefas;//considerado como infinito
first[i]=-1;
set[i]=0;
level[i]=0;
}
dist[myRank]=0;
set[myRank]=1;
state=0;
Distância Mínima – Implementação
//enviando meu conjunto para os meus vizinhos
for (i = 0; i < numeroDeTarefas; i++)
if (matrizVizinhanca[myRank][i] == 1)
{
//pede aos vizinhos para enviar
MPI_Send(set, numeroDeTarefas, MPI_INT,
i, tag, MPI_COMM_WORLD);
}
Distância Mínima – Implementação
while (state < numeroDeTarefas-1)
{
MPI_Recv(set, numeroDeTarefas, MPI_INT,
MPI_ANY_SOURCE, tag, MPI_COMM_WORLD,
&status);
origem=status.MPI_SOURCE;
level[origem]++;
for (i=0; i<numeroDeTarefas; i++)
{
if (set[i]==1)
{
if (dist[i]>level[origem])
{
dist[i]=level[origem];
first[i]=origem;
}
Distância Mínima – Implementação
//testando se meu state é menor ou igual ao
//level de todos os meus vizinhos
int continua=1;
for (j=0; j<numeroDeTarefas; j++)
if (matrizVizinhanca[myRank][j]==1 &&
state>=level[j])
{
continua=0;
break;
}
Distância Mínima – Implementação
if (continua){
state++;
//se minha distancia até j for igual a state,
//então o adiciono a set
for (j=0; j<numeroDeTarefas; j++){
if (dist[j]==state)
set[j]=1;
}
for (j=0; j<numeroDeTarefas; j++)
if (matrizVizinhanca[myRank][j]==1)
MPI_Send(set, numeroDeTarefas, MPI_INT, j,
tag, MPI_COMM_WORLD);
}
}
}
printf("processo %d: state=%d\n", myRank, state);
fflush(stdout);
}
Distância Mínima – Implementação
//imprimindo as distâncias
printf("processo %d: ", myRank);
for (i=0; i<numeroDeTarefas; i++)
printf("dist(%d)=%d, ", i, dist[i]);
printf("\n");
printf("processo %d: ", myRank);
for (i=0; i<numeroDeTarefas; i++)
printf("first(%d)=%d, ", i, first[i]);
printf("\n");
fflush(stdout);
//Finalização do MPI
MPI_Finalize();
}
Exercício
Desenvolva uma aplicação paralela em MPI para
multiplicar duas matrizes.
Referências
[1] N. MacDonald et alli, Writing Message Passing Programs with MPI,
Edinburgh Parallel Computer Centre Englewood Cliffs, NJ, Prentice--Hall, 1988
[2] P. S. Pacheco, Parallel Programming with MPI, Morgan Kaufman Pub,
1997
[3] Message Passing Interface Forum, MPI: A Message Passing Interface
Standard, International Journal of Supercomputer Applications, vol. 8, n. 3/4,
1994
[4] Valmir C. Barbosa, An Introduction to Distributed Algorithms, MIT Press,
1996
[5] Nancy A. Lynch, Distributed Algorithms, Morgan Kaufman Pub, 1997
[6] J. Jájá, Introduction to Parallel Algorithms, Addison-Wesley, 1992.
[7] M. J. Quinn, Parallel Computing Theory and Practice, 2nd edition,
McGraw-Hill, 1994.
[8] Ian Foster, Designing and Building Parallel Programs, Addison-Wesley,
1995.
[9] S. Akl, Parallel Computation – Models and Methods, Prentice-Hall, 1997.
Download