Você está na página 1de 408

COMPUTAÇÃO ESCALÁVEL

Computação Paralela e Distribuída


ROTEIRO

• Introdução

• Computação Paralela

• Computação Distribuída

• Aplicações de Computação Paralela e Distribuída


INTRODUÇÃO

• Um sistema escalável é aquele que apresenta


capacidade de funcionar quando há alteração do
seu contexto em relação ao seu tamanho para
atender necessidades do usuário

• Podemos construir aplicações e executá-las


considerando que podemos explorar muitos
recursos computacionais

• Para o usuário, a percepção da escalabilidade dos


sistemas fica oculta
INTRODUÇÃO

• Tradicionalmente, a grande maioria dos programas


escritos são programas sequenciais

• Para serem executados em um único computador


com uma CPU:
• o problema é quebrado em séries discretas de
instruções;
• as instruções são executadas uma após a outra;
• apenas uma instrução pode executar em um
determinado instante do tempo.
INTRODUÇÃO
COMPUTAÇÃO PARALELA

• Computação Paralela é definida como o uso


simultâneo de múltiplos recursos computacionais
para resolver um problema computacional

• Para ser executado em diversas CPUs:


• um problema é quebrado em partes discretas
que podem ser resolvidas concorrentemente
• cada parte é então quebrada em uma série de
instruções
• instruções de cada parte do programa são
executadas simultaneamente em diferentes
CPUs
COMPUTAÇÃO PARALELA
COMPUTAÇÃO PARALELA

• Os recursos computacionais podem incluir:

• um único computador com múltiplos


processadores
• um número arbitrário de computadores
conectados pela rede
• uma combinação de ambos
COMPUTAÇÃO DISTRIBUÍDA

• SISTEMA DISTRIBUÍDO é uma coleção de computadores independentes


aparentando ser um único computador

• Dois aspectos da definição:


• Hardware: as máquinas são autônomas
• Software: os usuários veem o sistema como uma única máquina

• CONCEITO CHAVE: TRANSPARÊNCIA

• A transparência pode ser entendida de duas formas:


• Transparência de recursos físicos (esconder dos
usuários a localização dos diversos recursos)
• Transparência para os sistemas
COMPUTAÇÃO DISTRIBUÍDA

• VANTAGENS
• Extensibilidade
• O sistema pode crescer
gradativamente
• Novos softwares podem ser
instalados gradativamente
• Compartilhamento de
recursos
• Recursos de alto custo
podem ser melhor utilizados
• Servidores de arquivo
• Servidores de e-mail
COMPUTAÇÃO DISTRIBUÍDA

• DESVANTAGENS

• Execução de backup é mais complexa


• Alocação de tempo de processamento
• Manutenção / Evolução do software
• Desempenho / Confiabilidade
• Dependência da rede utilizada
COMPUTAÇÃO PARALELA

• Programação Paralela → Mais complexa que a


Programação Sequencial

• Presença de erros dos programas sequenciais +


erros associados às interações entre os processos

• Erros dependentes do momento exato em que o


escalonador do SO realiza um chaveamento de
contexto

• Dificuldades de reproduzir e identificar os erros


COMPUTAÇÃO PARALELA

• Apesar da maior complexidade, há muitas áreas


nas quais a programação paralela é vantajosa

• Sistemas com vários processadores (máquinas


paralelas ou sistemas distribuídos)

• Aproveitamento do paralelismo para acelerar a


execução de um programa
APLICAÇÕES DE COMPUTAÇÃO PARALELA E
DISTRIBUÍDA

O mundo
é paralelo
APLICAÇÕES DE COMPUTAÇÃO PARALELA E
DISTRIBUÍDA
• Atualmente as aplicações comerciais fornecem uma força igual ou maior no
desenvolvimento de computadores mais rápidos
• Processamento de grandes quantidades de dados de forma sofisticada
 Bancos de Dados, mineração de dados
 Exploração de Petróleo
 Motores de Busca da Web, Serviços Web baseados em Negócios
 Imagens Médicas e Diagnóstico
 Gestão de Empresas Nacionais e Internacionais
 Modelagem Financeira e Econômica
 Realidade Virtual, principalmente na indústria do entretenimento
 Tecnologias Multimídia
 Ambientes Colaborativos de Trabalho
BIBLIOGRAFIA

1. Distributed Systems: Concepts and Design. G. Coulouris, J. Dollimore, T.


Kindberg. Addison-Wesley, 1994. ISBN: 0-201-62433-8. (Capítulos 4 e 5)

2. Distributed Operating Systems. A. S. Tanenbaum. Prentice-Hall, 1995.ISBN


0-13-219908-4. (Seções 2.4 e 2.5)

3. TOSCANI, S., OLIVEIRA, R., CARISSIMI, A., Sistemas Operacionais e


Programação Concorrente. Série didática do II-UFRGS, 2003.

4. https://computing.llnl.gov/tutorials/parallel_comp/
COMPUTAÇÃO ESCALÁVEL

Conceitos fundamentais
ROTEIRO
• Termos Gerais
• Tarefa / Tarefa Paralela
• Execução Serial / Execução Paralela
• Escalonamento
• Granularidade
• Sincronização
• Escalabilidade
• Processadores Multicore
• Speedup
TERMOS GERAIS

 Como em qualquer área, a computação


paralela também possui o seu “jargão”

 Os termos mais comumente utilizados,


associados à computação paralela, são
descritos nesta aula
TERMOS GERIAS

Tarefa (Task)
 Uma seção, logicamente discreta de trabalho
computacional, é tipicamente um programa ou um
conjunto de instruções de um programa executado
por um processador.

Tarefa Paralela (Parallel Task)


 Uma tarefa que pode ser executada por múltiplos
processadores.
TERMOS GERIAS

Execução Serial (Serial Execution)


 Execução de um programa sequencialmente, uma
instrução por vez. No sentido mais simples, isso é
o que ocorre em uma máquina de um processador.
No entanto, praticamente todas as tarefas têm
seções que devem ser executadas em série.
TERMOS GERIAS

Execução Paralela (Parallel Execution)


 Execução de um programa com mais de
uma tarefa. Instruções de mais de uma tarefa
podem ser executadas ao mesmo momento.
TERMOS GERIAS

Escalonamento
 Normalmente feito pelo sistema operacional.
Ele determina quais threads executam em
determinado momento.
TERMOS GERIAS

Granularidade
 É o tamanho do trabalho atribuído a cada thread
antes que elas se sincronizem.

 Indica a relação entre computação e comunicação


dos trechos de código gerados a partir da divisão
do problema a ser resolvido.
TERMOS GERIAS

Granularidade
 Um programa que é dividido em partes pequenas
entre as threads tem granularidade fina. Pequenos
trechos de código com comunicação alta -> maior
potencial de exploração de paralelismo.

 Um programa que faz com que suas threads


tenham muito trabalho antes de se sincronizarem
tem granularidade grossa. Grandes trechos de
código com comunicação baixa -> menor
potencial de exploração de paralelismo.
TERMOS GERIAS

Sincronização (Synchronization)
 A coordenação das tarefas paralelas, em tempo de
execução, é importante para garantir resultados
determinísticos. Sincronização neste contexto, se
refere às técnicas utilizadas para garantir essa
coordenação.
TERMOS GERIAS

Speedup
 Tempo da execução serial / Tempo da execução
paralela.
 Um dos indicadores mais simples e o mais
utilizado para quantificar o desempenho de um
programa paralelo.

Pipelinning
 Quebra de uma tarefa em etapas realizadas por
unidades diferentes de processamento.
BIBLIOGRAFIA

Introduction to Parallel Computing, Ananth Grama, Anshul


Gupta, George Karypis, Vipin Kumar - 2ª ed., Addison
Wesley
SSC-0742
PROGRAMAÇÃO CONCORRENTE

Aula 01 – Introdução à Programação Concorrente


Prof. Jó Ueyama
Créditos: Prof. Júlio C. Estrella
Créditos

Os slides integrantes deste material


foram construídos a par tr dos
conteúdos relacionados às referências
bibliográ fcas descritas neste
documento

1º Semestre de 2013 2
Visão Geral da Aula de Hoje

1º Semestre de 2013 3
DEFINIÇÃO

1º Semestre de 2013 4
Defnição
• Programação Concorrente / Programação Paralela
– Do inglês Concurrent Programming, onde
Concurrent signifca "acontecendo ao mesmo
tempo".
– Uma tradução mais adequada seria programação
concomitante. Entretanto, o termo programação
concorrente já está solidamente estabelecido no
Brasil. Algumas vezes é usado o termo Programação
Paralela com o mesmo sentdo (Toscani, 2003).

1º Semestre de 2013 5
Defnição
• Tradicionalmente, a grande maioria dos
programas escritos são programas sequenciais
• Para serem executados em um único
computador com uma CPU
– O problema é quebrado em séries discretas de
instruções.
• As instruções são executadas uma após a outra
– Apenas uma instrução pode executar em um
determinado instante do tempo.

1º Semestre de 2013 6
Defnição

problema

instruções

CPU

1º Semestre de 2013 7
Defnição
• Computação Paralela é defnida como o uso
simultâneo de múl tplos recursos
computacionais para resolver um problema
computacional
• Para ser executado em diversas CPUs
– Um problema é quebrado em partes discretas que
podem ser ser resolvidas concorrentemente
– Cada parte é então quebrada em uma série de
instruções
– Instruções de cada parte do programa são
executadas simultaneamente em diferentes CPUs

1º Semestre de 2013 8
Defnição
problema instruções

1º Semestre de 2013 9
Defnição
• Os recursos computacionais podem incluir:
– Um único computador com múltplos
processadores
– Um número arbitrário de computadores
conectados pela rede
– Uma combinação de ambos

1º Semestre de 2013 10
Defnição
• O problema computacional geralmente
demonstra característcas como a habilidade de
ser:
– Quebrados em partes de um trabalho que pode ser
resolvido de forma simultânea
– Executar múltplas instruções do programa a
qualquer momento no tempo
– Resolvido em menos tempo com vários recursos de
computação do que com um único recurso
computacional

1º Semestre de 2013 11
Defnição
• A computação paralela é uma evolução da
computação sequencial, que tenta imitar o
estado das coisas no mundo real: muitos
eventos complexos inter-relacionados
acontecendo ao mesmo tempo, mas dentro
de uma sequência.

1º Semestre de 2013 12
Defnição
• Programação Paralela Mais complexa que a
Programação Sequencial.
• Presença de erros dos programas sequenciais + erros
associados as interações entre os processos
• Erros dependentes do momento exato em que o
escalonador do SO realiza um chaveamento de contexto
– Difculdades de reproduzir e identfcar os erros
• Apesar da maior complexidade, há muitas áreas nas quais
a programação paralela é vantajosa.
– Sistemas com vários processadores (máquinas paralelas ou
sistemas distribuídos)
• Aproveitamento do paralelismo para acelerar a execução do
programa.

1º Semestre de 2013 13
Defnição
• A programação paralela é natural para vários
tpos de aplicações, principalmente para
aquelas que apresentam paralelismo
implícito
• Aplicações com paralelismo implícito:
– aquelas para as quais pode-se distnguir
facilmente funções para serem realizadas em
paralelo

1º Semestre de 2013 14
Motvação
• Spooling de Impressão

PC PC PC

Usuários Servidor de Impressão

1º Semestre de 2013 15
Motvação
• Organização de um servidor de impressão

Receptor Transmissor

Protocolo

Escritor

Leitor Impressor

1º Semestre de 2013 16
MOTIVAÇÃO

1º Semestre de 2013 17
O Mundo é Paralelo
Formação de Galáxias Padrões dos oceanos

Movimentação dos planetas

Padrões do tempo

Tráfego na hora do rush Movimentação da placa tectônica


Pedido de um hamburger

Linha de montagem de carros Construção de aviões


1º Semestre de 2013 18
Usos para Computação Paralela
• A computação paralela tem tem sido utlizada para
modelar di fceis problemas cien tfcos e de
engenharia encontrados no mundo real.
• Exemplos
– Atmosfera, Terra, Meio Ambiente
Física: Aplicada, Nuclear, Partculas, Matéria Condensada, Alta
pressão, Fusão, Fotônica
– Biociências, Biotecnologia, Genétca
– Química, Ciências Moleculares
– Geologia, Sismologia
– Engenharia Mecânica - De próteses à nave espacial
– Engenharia Elétrica, Projeto de circuito, Microeletrônica
– Ciência da Computação, Matemátca

1º Semestre de 2013 19
Usos para Computação Paralela

1º Semestre de 2013 20
Usos da Computação Paralela
• Atualmente as aplicações comerciais fornecem uma força
igual ou maior no desenvolvimento de computadores
mais rápidos.
– Processamento de grandes quantdades de dados de forma
sofstcada
• Bancos de Dados, mineração de dados
• Exploração de Petróleo
• Motores de Busca da Web, Serviços Web baseados em Negócios
• Imagens Médicas e Diagnóstco
• Gestão de Empresas Nacionais e Internacionais
• Modelagem Financeira e Econômica
• Realidade Virtual, principalmente na indústria do entretenimento
• Tecnologias Multmídia
• Ambientes Colaboratvos de Trabalho

1º Semestre de 2013 21
Usos da Computação Paralela

1º Semestre de 2013 22
OBJETIVOS DA
PROGRAMAÇÃO PARALELA

1º Semestre de 2013 23
Razões - Computação Paralela
• Economizar tempo e dinheiro
– Em teoria, jogar mais recurso em uma tarefa vai
encurtar seu tempo para a conclusão, com
potenciais economias de custos. Clusters
paralelos podem ser construídos a partr de
componentes baratos

1º Semestre de 2013 24
Razões – Computação Paralela
• Há uma demanda contnua por maior
processamento
• Áreas que requerem grande processamento
computacional incluem:
– Modelagem Numérica
– Simulação de problemas cientfcos e de engenharia
• Para esses casos por exemplo, a computação
deve ser completada dentro de um período de
tempo razoável

1º Semestre de 2013 25
Razões - Computação Paralela
• Resolver grande problemas
– Muitos problemas são tão grandes / complexos
que é impratcável ou impossível resolvê-los num
único computador, especialmente quando a
memória é limitada.
– Exemplo:
• Motores de busca da Web / Bases de dados de
processamento de milhões de transações por segundo
(Problemas que exigem petafops
e petabytes de recursos de computação.)

1º Semestre de 2013 26
Razões - Computação Paralela
• Prover Concorrência
– Um único recurso de computação pode fazer
uma tarefa de cada vez. Vários podem fazer
muitas tarefas simultaneamente
– Exemplo:
• AccessGrid – Provê uma rede de colaboração global
em que as pessoas podem se reunir e conduzir o
trabalho “virtualmente”. (www.accessgrid.org)

1º Semestre de 2013 27
Razões - Computação Paralela
• Recursos não-locais
– Usar recursos computacionais em uma rede
como a Internet quando recursos locais são
escassos.
• Exemplo:
– SETI@home (setathome.berkeley.edu) utliza mais
de 330 mil computadores para um poder
computacional de 528 TeraFLOPS (Ago. 2008)
– Folding @ home (folding.stanford.edu) utliza mais
de 340 mil computadores para um poder
computacional de 4.2 petaFLOPS (Nov. 2008)

1º Semestre de 2013 28
Razões - Computação Paralela
• Limite da computação serial
– Razões fsicas e prátcas restringem a construção
de computadores cada vez mais rápidos
• Velocidade de transmissão
• Limites a miniaturização
• Limitações econômicas

1º Semestre de 2013 29
Razões - Computação Paralela
• Arquiteturas de computadores atuais são
cada vez mais dependentes do paralelismo
em nível de hardware para melhorar o
desempenho

1º Semestre de 2013 30
Razões – Computação Paralela
• Utliza mais de um computador ou um
computador com mais de um processador, para
resolver um determinado problema
• Motvação
– N computadores operando simultanealmente pode
atngir o resultado N vezes mais rápido – Não será N
vezes mais rápidos por uma série de razões
– Outros motvos incluem: tolerância a falhas, grande
quantdade de memória disponível, etc.

1º Semestre de 2013 31
Medida Simples
• Speedup
– A relação entre o tempo gasto para executar
uma tarefa com um único processador e o tempo
gasto com N processadores, ou seja, Speedup é a
Medida do ganho em tempo
• S = T(1) / T (N)
• Ou seja, Speedup é a medida do ganho em tempo

1º Semestre de 2013 32
Medidas Simples
• Lei de Amdahl
– htp://en.wikipedia.org/wiki/Amdahl%27s_law
• Utlizar essa Lei, juntamente com o cálculo do
Speedup para o Primeiro Trabalho da
Disciplina.

1º Semestre de 2013 33
Leitura
Recomendada

1º Semestre de 2013 34
Leitura Recomendada e Tarefa
• Introducton to Parallel Computng, Ananth Grama,
Anshul Gupta, George Karypis, Vipin Kumar - 2ª ed.,
Addison Wesley
– Capítulo 01
• Formato das apresentações
• Formato da parte escrita
• Tarefa
– Escreva um programa implementando uma calculadora
paralela

1º Semestre de 2013 35
Bibliografa
• TOSCANI, S., OLIVEIRA, R., CARISSIMI, A.,
Sistemas Operacionais e Programação
Concorrente. Série didátca do II-UFRGS,
2003.
• htps://computng.llnl.gov/tutorials/parallel_
comp/

1º Semestre de 2013 36
Dúvidas

1º Semestre de 2013 37
Próxima Aula...
• Revisão de Arquiteturas Paralelas

1º Semestre de 2013 38
COMPUTAÇÃO ESCALÁVEL

Paralelismo, Concorrência e
Escalabilidade
ROTEIRO

• Arquiteturas de Memória

• Modelos de Programação
ARQUITETURAS DE MEMÓRIA

MEMÓRIA COMPARTILHADA DIVISÃO EM


DUAS
CLASSES:
• Múltiplos processadores
compartilham os mesmos
recursos de memória em um • UMA – tempo
espaço de endereçamento de acesso
global uniforme
• Modificações efetuadas em uma
região de memória por um • NUMA – tempo
processador são visíveis a de acesso não
todos os outros processadores uniforme
ARQUITETURAS DE MEMÓRIA

UNIFORM MEMORY ACCESS (UMA)

• Comum em processadores simétricos (SMP)


• Tempo de acesso igual para toda a memória
• Coerência de Cache
 Se um processador atualiza um dado na
memória compartilhada, isso tem que ser
propagado para os outros processadores
(cache interna à CPU)
 Normalmente feita em hardware
ARQUITETURAS DE MEMÓRIA

UMA
ARQUITETURAS DE MEMÓRIA

NON-UNIFORM MEMORY ACCESS

• SMPs conectados por canais de comunicação


• O espaço de endereçamento ainda é global e um
SMP pode acessar diretamente a memória do outro
• O tempo de acesso a uma posição de memória varia
se ela pode ser acessada localmente ou em um
processador remoto através dos canais de
comunicação
• Se existe Coerência de Cache, a arquitetura é
chamada de CC-NUMA (Cache Coeherent NUMA)
ARQUITETURAS DE MEMÓRIA

NUMA
ARQUITETURAS DE MEMÓRIA

MEMÓRIA COMPARTILHADA
VANTAGENS DESVANTAGENS

• O espaço de • Falta de escalabilidade


endereçamento
global permite um • Aumentando o número de CPUs,
modelo de aumenta o tráfego entre memória
programação mais e CPU (bottleneck de von
amigável (conhecido) Neumann)

• O compartilhamento • É de responsabilidade do
de dados entre as programador a sincronização
tarefas é rápido dos acessos à memória global
compartilhada
ARQUITETURAS DE MEMÓRIA

MEMÓRIA DISTRIBUÍDA
• Sistemas de memória distribuída possuem uma rede
de comunicação para interconectar os processadores
• Cada processador tem sua própria memória local
• Não existe um espaço de endereçamento global, um
processador tem acesso somente a sua memória
• É tarefa do programador determinar quando e como
um dado é propagado de um processador para o outro
• A sincronização das tarefas é também função do
programador
ARQUITETURAS DE MEMÓRIA

MEMÓRIA DISTRIBUÍDA
VANTAGENS DESVANTAGENS

• A memória é escalável • O programador precisa


com o número de cuidar de muitos detalhes
processadores associados à comunicação
• Mais Processadores → de dados entre os
Maior Quantidade de processadores
Memória • Dificuldade de mapear
• Acesso rápido à memória estruturas de dados
do próprio processador projetadas para uma
sem interferência e memória global com esta
sobrecarga da coerência organização de memória
da cache
MODELOS DE PROGRAMAÇÃO

• Modelos de programação paralela existem como


uma abstração acima da arquitetura de hardware e
de memória

• Apesar de não ser evidente, os modelos não são


específicos para um determinado tipo de
arquitetura

• Qualquer modelo pode (teoricamente) ser


implementado em qualquer hardware
MODELOS DE PROGRAMAÇÃO

MODELO DE MEMÓRIA COMPARTILHADA

• Neste modelo as • VANTAGEM → Para o


tarefas programador
compartilham um  Não existe a
espaço de endereço necessidade de
comum, onde elas comunicação
podem ler e escrever explícita de dados
simultaneamente entre as tarefas

• Mecanismos como semáforos podem ser utilizados


para controlar o acesso à memória compartilhada
MODELOS DE PROGRAMAÇÃO

MODELO DE MEMÓRIA DISTRIBUÍDA


• Conjunto de tarefas que • Tarefas trocam dados
utilizam a memória local através de
durante a computação comunicação,
• Várias tarefas podem residir enviando e recebendo
na mesma máquina mensagens

• A transferência de dados em geral requer operações de


cooperação a serem executadas por cada processo
Exemplo:
• Operação de envio deve ter uma operação de recepção
correspondente
MODELOS DE PROGRAMAÇÃO

MODELO DE
MEMÓRIA
DISTRIBUÍDA
BIBLIOGRAFIA

1. Introduction to Parallel Computing, Ananth Grama, Anshul Gupta, George


Karypis, Vipin Kumar - 2ª ed., Addison Wesley

2. https://computing.llnl.gov/tutorials/parallel_comp/
COMPUTAÇÃO ESCALÁVEL

Paralelismo em
Sistemas Multicore
ROTEIRO

• Arquitetura de Von Neumann


• Classificação das Arquiteturas de Computadores
• Arquitetura Multicore
ARQUITETURA DE VON NEUMANN
 Batizada em homenagem ao matemático húngaro John Von
Neumann, que em 1945 introduziu os conceitos básicos dos
computadores atuais.

 O conceito mais importante é o de programa armazenado na


memória. Antes disso, os programas eram feitos através de
interligações físicas dos circuitos.
CLASSIFICAÇÃO DAS ARQUITETURAS
 Várias maneiras foram propostas para a classificação das
arquiteturas de computadores

 Uma das mais simples, e talvez por isso, mais utilizada é a


classificação de Flynn
CLASSIFICAÇÃO DAS ARQUITETURAS

Classificação de Flynn (em uso desde 1966)


 Distingue arquiteturas de computadores de acordo com
a multiplicidade de fluxos simultâneos de processamento
de instruções e de acessos à memória

 Cada um deles pode ser:


 Simples ou Múltiplos
CLASSIFICAÇÃO DAS ARQUITETURAS
4 classes

SISD SIMD
Single Instruction, Single Instruction,
Single Data Multiple Data

MISD MIMD
Multiple Instruction, Multiple Instruction,
Single Data Multiple Data
CLASSIFICAÇÃO DAS ARQUITETURAS

SISD - Single Instruction, Single Data


 Um computador não paralelo, a arquitetura básica de Von
Neumann
 Fluxo Simples de Instruções: apenas um fluxo de

instruções e processado de cada vez


 Fluxo Simples de Dados: um único fluxo de dados

existe entre processador e memória


 Execução determinística

 É o mais antigo e comum tipo de computador usado


atualmente
CLASSIFICAÇÃO DAS ARQUITETURAS
SISD
CDC-7600

CRAY-1 PDP-1

IBM-360 UNIVAC1
CLASSIFICAÇÃO DAS ARQUITETURAS

SIMD - Single Instruction, Multiple Data


 Única instrução: todas as unidades de processamento
executam a mesma instrução
 Vários dados: cada unidade de processamento pode
operar em um elemento de dados diferentes
 Mais adequado para problemas específicos caracterizados
por um alto grau de regularidade, tais como
gráficos/processamento de imagens
 A maioria dos computadores modernos
 Particularmente aqueles com as unidades de processadores
gráficos (GPUs) empregam SIMD instruções e unidades de
execução
CLASSIFICAÇÃO DAS ARQUITETURAS
SIMD

CRAY Y-MP ILLIAC-IV

Thinking Machines CM-2

Maspar CRAY X-MP


CLASSIFICAÇÃO DAS ARQUITETURAS

MISD - Multiple Instruction, Single Data


 Único fluxo de dados alimentado em várias unidades de
processamento.
 Cada unidade de transformação opera sobre os dados de
forma independente por meio de fluxos de instruções
independentes
 Poucos exemplos concretos desta categoria de
computadores
 Experimental Carnegie-Mellon C.mmp (1971)
 Alguns autores consideram que unidades de execução
em pipeline representam essa categoria
CLASSIFICAÇÃO DAS ARQUITETURAS

MIMD - Multiple Instruction, Multiple Data


 Cada processador pode executar um fluxo de instruções
diferentes
 Cada processador pode trabalhar com diferentes fluxos
de dados
 A execução pode ser síncrona ou assíncrona
 Atualmente o tipo mais comum de computador paralelo
 Exemplos: a maioria dos supercomputadores atuais,
clusters de computadores paralelos, multi-core
CLASSIFICAÇÃO DAS ARQUITETURAS
MIMD

Intel / AMD

NVIDIA

Fonte: 4 e 5
ARQUITETURA MULTICORE

Sistemas Multicore
 Consiste em várias cópias de um processador
dentro de um único chip
 Cada cópia é chamada de núcleo ou core
 Essas cópias são interconectadas por um
barramento ou outro mecanismo de comunicação
 São utilizados para executar diferentes tarefas de
forma simultânea ou uma mesma tarefa mais
rapidamente
 Consomem menos energia que alternativas mais

complexas como processadores superescalares


ARQUITETURA MULTICORE
BIBLIOGRAFIA

1.Introduction to Parallel Computing, Ananth Grama, Anshul


Gupta, George Karypis, Vipin Kumar - 2ª ed., Addison Wesley
- Capítulo 01
2. Aula 1 – Microprocessadores - IFSC
3.Arquitetura de Computadores
4.https://www.colfax-intl.com/software/intel-data-center-
manager
5.https://www.techpowerup.com/239994/nvidia-forbids-geforce-
driver-deployment-in-data-centers
OpenMP

Slides baseados em tutorial de Tim Mattson da


Intel
O que é OpenMP ?

• Uma especificação para um conjunto de diretivas de


compilação, rotinas de biblioteca e variáveis de sistema
que podem ser utilizadas para especificar paralelismo
baseado em memória compartilhada
• Portável, incluindo plataformas Unix e Windows NT
• Disponível em implementações Fortran e C/C++
• Definida e endossada por um grupo grande de
fabricantes de software e hardware
• Suporta paralelismo de granulosidade fina e grossa
Origens

• No início dos anos 90, fabricantes de máquinas com


memória compartilhada forneciam extensões para
programação paralela em Fortran
• As implementações permitiam ao usuário inserir
diretivas para indicar onde loops deveriam ser
paralelizados e os compiladores eram responsáveis pela
paralelização
• Implementações funcionalmente parecidas, mas não
portáveis e começaram a divergir
• AINSI X3H5 em 1994 foi a primeira tentativa de
padronização
Origens

• A especificação padrão OpenMP começou em 1997 partindo do


padrão X3H5 graças ao aparecimento de novas arquiteturas de
máquinas de memória compartilhada
• Alguns parceiros na especificação:
– Compaq, HP, Intel, IBM, Silicon, Sun
– Absoft, GENIAS, Myrias, The Portland Group
– ANSYS, Dash, ILOG CPLEX, Livermore, NAG
• A API para Fortran foi liberada em Outubro de 1997 e para
C/C++ no final de 1997
• Última versão OpenMP 5.0 (Novembro 2018)
Objetivos

• Prover um padrão para uma variedade de plataformas


e arquiteturas baseadas em memória compartilhada
• Estabelecer um conjunto limitado e simples de diretivas
para programação utilizando memória compartilhada
• Prover capacidade para paralelizar um programa de
forma incremental
• Implementar paralelismo com granulosidade fina e
grossa
• Suportar Fortran, C e C++
Modelo de programação

• Paralelismo baseado em threads:


– Se baseia na existência de processos consistindo de várias threads
• Paralelismo explícito:
– Modelo de programação explícito e não automático, permitindo total
controle da paralelização ao programador
• Modelo fork-join
– Os programas OpenMP começam como um único processo denominado
master thread, que executa seqüencialmente até encontrar a primeira
construção para uma região paralela
– FORK: a master thread cria um time de threads paralelos
– As instruções que estão dentro da construção da região paralela são
executadas em paralelo pelas diversas threads do time
– JOIN: quando as threads finalizam a execução das instruções dentro da
região paralela, elas sincronizam e terminam, ficando somente ativa a
master thread
OpenMP Basic Defs:
SolutionEndStack
User

Application

Directives, Environment
OpenMP library
Compiler variables

OpenMP Runtime library

OS/system support for shared memory and threading

Proc1 Proc2 Proc3 ProcN

Shared Address Space


Modelo de programação

• Baseado em diretivas de compilação:


– o paralelismo é especificado através do uso de diretivas para o compilador
que são inseridas em um código Fortran ou C/C++
• Suporte a paralelismo aninhado:
– construções paralelas podem ser colocadas dentro de construções paralelas
e as implementações podem ou não suportar essa característica
• Threads dinâmicas:
– o número de threads a serem utilizadas para executar um região paralela
pode ser dinamicamente alterado
Exercício 1: Hello World (uma thread)

void main ( )
{
int ID = 0;
printf(“hello(%d)”, ID);
printf(“world(%d)\n”,ID);
}
Diretivas C/C++

• Formato
# p ragm a o m p n o m e d a d iretiva [cláu sula, ...] n ew lin e
N ecessária p ara U m a d iretiva O p cio n al. P od em N ecessária. D eve
to d as as d iretivas válid a q u e d eve ap arecer em ser in serid o ap ó s o
ap arecer d ep o is d a q u alqu er o rd em e b lo co estru tu rad o
p rag m a e an tes d as rep etid as qu an do q u e está d entro d a
cláu su las n ecessário d iretiva.

• Exemplo:
– #pragma omp parallel default(shared) private(beta,pi)
• Seguem o padrão de diretivas de compilação para C/C++
• Cada diretiva se aplica no máximo a próxima instrução,
que deve ser um bloco estruturado
Construtor de região PARALLEL
• Fork-join
– Quando uma thread chega na região paralela, ela cria um time de threads e
se torna a mestre do time. Ela faz parte do time e tem o número 0.
– O código que começa no início da região paralela é duplicado e todas as
threads o executam
– Existe uma barreira implícita no final da seção paralela, e somente o
mestre continua a executar após esse ponto
• O número de threads na região paralela é definido por:
– Uso da rotina omp_set_num_threads ()
– Na diretiva #pragma omp parallel num_threads ()
– Uso da variável de ambiente OMP_NUM_THREADS
– Default da implementação
Exercício 1: Hello World (multithreaded)
Arquivo header OpenMP
#include <omp.h>
void main ( )
{ Início da região paralela
com número default de threads
#pragma omp parallel
{
int ID = 0;
printf(“hello(%d)”, ID);
printf(“world(%d)\n”,ID);
} Final da região paralela
}
Exercício 1: Hello World (multithreaded)

#include <omp.h>
void main ( )
{
#pragma omp parallel Opções para compilação e
{ ligação
gcc -fopenmp
int ID = 0;
printf(“hello(%d)”, ID);
printf(“world(%d)\n”,ID);
}
Exercício 1: Hello World (multithreaded)

Cada thread imprime seu número:


#include <omp.h>
void main ( )
{
#pragma omp parallel Rotina da biblioteca para
{ obter número da thread
int ID = omp_get_thread_num();
printf(“hello(%d)”, ID);
printf(“world(%d)\n”,ID);
}
Criação de threads

• Para criar 4 threads na região paralela:


double A[1000]
omp_set_num_threads(4)
#pragma omp parallel
{
int ID = omp_get_thread_num();
fa(A,ID);
}
• Cada thread executa uma cópia do código que está no
bloco estruturado
Criação de threads

• Para criar 4 threads na região paralela:


double A[1000]
#pragma omp parallel num_threads(4)
{
int ID = omp_get_thread_num();
fa(A,ID);
}
• Cada thread executa uma cópia do código que está no
bloco estruturado
Criação de threads
Uma cópia de A é compartilhada
entre as threads
double A[1000]

omp_set_num_threads(4)

fA(0,A) fA(1,A) fA(2,A) fA(3,A)

Todas as threads esperam aqui


para continuar
Integração numérica
4.0 Matematicamente, sabemos que:

 4.0
(1+x2) dx = 
2.0 0

Podemos aproximar a
integral por uma soma de
retângulos:

0.0
X
1.0
 F(x )∆x  
i
i=0

Onde cada retângulo tem


largura ∆x e altura F(x ) no
meio do intervalo i
Programa sequencial Pi

static long num_steps = 100000;


double step;
void main ()
{ int i; double x, pi, sum = 0.0;
step = 1.0/(double) num_steps;
for (i=0;i< num_steps; i++){
x = (i+0.5)*step;
sum = sum + 4.0/(1.0+x*x);
}
pi = step * sum;
}
Programa paralelo Pi

• Crie uma versão paralela do programa Pi usando uma


construção paralela
• Divida o número de steps entre as threads
• Crie um vetor compartilhado para armazenar as somas
parciais
• Utilize as rotinas:
– omp_set_num_threads
– omp_get_thread_num
– omp_get_num_threads
Programa paralelo Pi
Capítulo

2
Introdução a Computação Paralela com o Open
MPI

Sandro Athaide Coelho

Abstract

This paper introduces an overview about Distributed Parallel Computing and related
technologies using Message Passing Interface approach (MPI). MPI is a standard
specification to message-passing systems sponsored by MPI-Forum.

Resumo

Este minicurso introduz uma visão geral sobre programação paralela distribuída
através da abordagem de message passing. O MPI (Message Passing Interface) é uma
especificação mantida pelo MPI-Forum e se tornou um padrão para comunicação de
dados em Computação Paralela e de Alto Desempenho.

2.1. Introdução
Um dos grandes desafios da Ciência da Computação atualmente é viabilizar soluções
computacionais que reduzam o tempo de processamento e forneçam respostas ainda
mais precisas. Frequentemente surgem propostas com as mais diversas abordagens que
exploram novas formas de resolver tais problemas ou tentam ainda melhorar as soluções
existentes.
Uma das grandes áreas que se dedica a propor tais melhorias é a computação
paralela e de alto desempenho – HPC (High Performance Computing) do inglês – que
tem como base várias subáreas da Ciência da Computação, como por exemplo,
arquitetura de computadores, linguagens de programação, compiladores, teoria da
computação e computabilidade, recebendo ainda , influências de varias outras áreas, tais
como computação gráfica.
Este minicurso introduzirá o padrão MPI (Message Passing Interface). O MPI é
um conjunto de especificações de protocolos de comunicação utilizados em HPC,
desenvolvido pelo consórcio MPI Forum, composto por pesquisadores e pela indústria.

24
A linguagem de programação utilizada durante o minicurso será o C e o
conjunto de bibliotecas do Open MPI. Esta implementação fornece ainda compiladores
para as linguagens de programação Fortran e C++ que não serão abordadas no
minicurso, porém, após o entendimento dos exemplos podem ser facilmente adaptados.
O minicurso está organizado da seguinte maneira. A seção 2.2 apresenta
motivações para aprender computação paralela e suas aplicações. A seção 2.3 introduz
aspectos de arquitetura de computadores. Já a seção 2.4 mostra a classificação de Flynn.
Na seção 2.5 é introduzido os dispositivos de interconexão voltados para computação
paralela. Na seção 2.6 há uma explicação sobre Clusters e Grids. Na seção 2.7 é
mostrado algumas métricas para computação paralela. Na seção 2.8 é apresentado o
padrão MPI e sua API, enquanto a seção 2.9 apresenta uma conclusão sobre o tema.

2.2. Motivações para Computação Paralela


Técnicas que otimizem o tempo de processamento, algoritmos mais eficientes e
computadores mais rápidos abrem novos horizontes possibilitando realizar tarefas que
antes eram inviáveis ou mesmo levariam muito tempo para serem concluídas. Sutter
(2005), em seu artigo “The free lunch time is over”, afirma que não podemos mais
esperar que nossos algoritmos fiquem mais rápidos apenas com atualizações de CPU.
Muitos aplicativos se aproveitaram do fenômeno do “almoço grátis”, com ganhos
regulares de desempenho por décadas, simplesmente esperando novas versões de CPU,
memórias e discos mais rápidos.
A Lei de Gordon Moore [Moore 1965] previa um crescimento exponencial de
transistores dos chips – 100% a cada 18 meses – pelo mesmo custo. Este crescimento
traduzia em ganhos exponenciais de velocidade do Clock e no número de instruções
executadas. Porém este crescimento não pode mais, até o momento, superar os limites
físicos e problemas como geração e dissipação de calor além do alto consumo de
energia. Existem ainda problemas relativo ao custo no desenvolvimento de pesquisas
para reduzir componentes, sem quebrar a compatibilidade do modelo atual.
A saída da indústria para superar tal limitação tem sido disponibilizar mais de
um núcleo nos processadores, ao invés se concentrarem somente no aumento do Clock.
Infelizmente algoritmos estritamente seriais não são beneficiados.
Com os avanços da ciência, o método cientifico (observação, teoria e
experimentação ) ganhou um importante aliado: a simulação numérica. Este por sua vez
passou a ser definido como método cientifico moderno [Quinn 2003]. Ainda segundo
Quinn (2003) “a simulação numérica é uma importante ferramenta para os cientistas que
as vezes não podem testar suas teorias, seja pelos custos e tempo que isto envolve, por
questões éticas ou ainda quando é impossível realizá-las”.
Simular eventos naturais como a previsão do tempo, dinâmica de fluídos,
sequenciamento genético ou mesmo buscar novas drogas para a cura de doenças
requerem modelos mais complexos e com grande poder computacional. Devido a
magnitude de tais problemas, estes por sua vez são categorizados como os Grandes
Desafios da Ciência[Quinn 2003].
Durante a construção de tais modelos, além da preocupação direta com a solução
do problema, é necessário atender requisitos como precisão e/ou tempo total de

25
processamento -“Wall Clock Time”. Para estes aspectos, devem ser avaliadas a
utilização de tecnologias que suportem tais requisitos e ainda promovam escalabilidade.
Este último ponto é muito importante pois afeta diretamente a continua evolução e
aprimoramento da abordagem numérica proposta.
Fora do contexto científico, vivenciamos também uma explosão no volume de
dados. As corporações, por exemplo, buscam cada vez mais ferramentas que
transformem estes dados em informações valiosas, com o objetivo de fornecer respostas
as necessidades de seus negócios e os ajudem a otimizar seus processos.
Em geral, tais tecnologias tem como base a tríade Recognition – Minning –
Synthesis [Chen 2008], que utilizam gigantescos datasets e lançam mão do uso de
soluções massivamente paralelas para processar e obter suas respostas.
Áreas emergentes como a Web semântica, por exemplo, buscam algoritmos e
formas de resolver a escalabilidade com ênfase na capacidade de processamento de
tarefas mais complexas e na habilidade de processar grandes datasets [Peiqiang et al.
2009].
Há fascinantes aplicações e excelentes oportunidades onde a computação
paralela pode representar ganhos de desempenho significativos. Poderíamos relacionar
inúmeros outros casos, porém acredito que os exemplos acima são suficientes e nos
motivam a investir tempo para conhecimento e aprimoramento do assunto.

2.3. Arquitetura de Computadores

2.3.1. Memória distribuída (Distributed Memory)


Ambientes computacionais onde cada unidade de processamento possui suas próprias
memórias e processadores(Figura 2.1), que estão conectados através de um barramento
de rede onde trocam informações, são classificados como ambiente de memória
distribuída.

Figura 2.1. Exemplo de arquitetura paralela distribuída

A grande vantagem desta configuração é a flexibilidade em expandir ou reduzir


quantas unidades de processamento forem necessárias, com o objetivo de dimensionar o
seu parque computacional de acordo com o problema a ser tratado.

26
Os modelos que exploram ambientes computacionais de memória distribuída são
os que adotam o paradigma de message passing (troca de mensagens). Tais modelos são
formados por rotinas de comunicação e sincronização de tarefas - sendo o MPI um
exemplo - que podem ser ativadas a partir de três modos:
• disponibilidade: o processo somente poderá enviar uma mensagem se o receptor
estiver disponível;
• standard: uma mensagem pode ser enviada mesmo se não houver um receptor
para ele;
• síncrono: similar ao modo padrão, porém o processo de envio só é considerado
como concluído quando o receptor inicia a operação de recebimento.
Estes modelos são altamente portáveis e habilitam a execução de programas nos
mais diferentes tipos de máquinas paralelas.

2.3.2. Memória compartilhada (Shared Memory)


Nesta arquitetura vários processadores compartilham o mesmo pool de memórias
(Figura 2.2). A comunicação entre eles é realizada através de leitura e escrita neste
espaço compartilhado que podem ser explorados por modelos de programação
relativamente simples.

Figura 2.2. Exemplo de arquitetura paralela de memória compartilhada

A vantagem desta arquitetura é a velocidade e simplicidade dos programas,


superando por exemplo o modelo distribuído, que exige uma programação mais
elaborada e depende de uma camada de interconexão para a troca de informações. Já a
principal desvantagem está na escalabilidade: os programas ficam limitados a
capacidade física do computador onde estão sendo executados.
No passado, máquinas com esta arquitetura apresentavam custos elevados,
porém com a decisão da indústria em trabalhar ganhos de desempenho, adicionando

27
vários núcleos em um mesmo chip, conhecidos atualmente como cores, reduziu
significativamente os preços desta tecnologia.
Os modelos de programação projetados para este tipo de arquitetura geralmente
usam processos com baixo custo computacional. Estes por sua vez são conhecidos como
Threads. As abordagens mais conhecidas são as disponíveis nos sistemas operacionais,
como o Pthreads em sistemas Unix Like e WinThreads no Windows .
Há ainda modelos de alto nível como o OpenMP, que fornece uma API de alto
nível, portável, composta de diretivas de compilação, bibliotecas de execução e
variáveis de ambientes. O OpenMP é baseado no modelo fork-join (Figura 2.3).

Figura 2.3. Fork-join no OpenMP

A seguir é apresentado um exemplo de uma função que soma um vetor


paralelamente, usando o OpenMP (Figura 2.4).

Figura 2.4. OpenMP: a diretiva #pragma omp parallel for informa ao compilador
que a região deve ser paralelizada.

2.3.3. UMA (Uniform Memory Access)


É possível ainda subdividir as duas grandes classificações anteriores: Memória
Distribuída e Memória Compartilhada, de acordo com vários critérios, dentre os quais
citamos o tempo de acesso à memória.
O modelo UMA (Uniform Memory Access) é uma arquitetura de memória
compartilhada, sendo o tempo de acesso ao pool de memórias uniforme, independente
da localização do processador. Cada processador possui um cache privado que é
sincronizado com a memória principal através de algoritmos de cache-coherence
embarcados no hardware [Martin et al. 2012].
Devido as suas características, este modelo tornou-se muito adequado a
aplicações de uso geral.

28
2.3.4. NUMA (Non-Uniform Memory Access)
Quando o tempo de acesso de memória está intrinsecamente relacionado a localização
do processador, este grupo é denominado como NUMA. Esta arquitetura é desenhada
para prover o compartilhamento total de recursos, executando um mesmo sistema
operacional. Como a memória de todas as máquinas participantes são mapeadas em um
mesmo espaço de endereçamento, a comunicação se dá por uma rede de interconexão.

2.4. Classificação de Flynn


Flynn (1972) elaborou uma classificação muito difundida e aceita atualmente para
arquiteturas paralelas (Figura 2.5). Foram usados como parâmetros o fluxo de instruções
e de dados para gerar a tabela de enquadramento das arquiteturas. Como resultado,
temos as 4 (quatro) grandes classes, relacionadas a seguir:
• Single Instruction, Single Data (SISD): nesta categoria temos os computadores
que não exploram nenhum tipo de paralelismo. Uma única unidade de controle é
responsável por processar um único fluxo de instruções num único fluxo de
dados. Os exemplos nesta categoria são os antigos computadores pessoais,
antigos mainframes e demais máquinas que implementam a arquitetura
tradicional de von Neumann [Navaux 2003];
• Single Instruction, Multiple Data (SIMD): projetos de arquiteturas onde uma
única instrução é executada simultaneamente em múltiplos fluxos de dados.
Navaux (2003) ressalta que para que este tipo de processamento ocorrer, a
unidade de memória não pode ser implementada como um único módulo.
Enquadram-se neste grupo máquinas Array como o Cray J-90, o CM-2e o
MasPar, além das GPUs [Hennesy, 2012]. Seriam categorizados como MISD, as
arquiteturas que apresentam múltiplos fluxos de instrução e executam suas
instruções sob um mesmo fluxo de dados;
• Multiple Instruction, Single Data (MISD): esta categoria é fonte de divergência
entre os vários cientistas e pesquisadores da área de arquitetura de
computadores. De acordo com Navaux (2003), Mattson (2005) nenhum sistema
conhecido se encaixa nesta categoria. Entretanto Quinn (2003) aponta como
exemplo para esta categoria o systolic array;
• Multiple Instruction, Multiple Data (MIMD): finalmente encaixam-se aqui os
multiprocessadores (memória compartilhada) e os multicomputadores (memória
privada). As duas arquiteturas apresentam múltiplas unidades de processamento
que manipulam diferentes fluxos de instrução com diferentes fluxos de dados .

29
Figura 2.5. Classificação de Flynn.

2.5. Dispositivos de Interconexão


Canais de comunicação de alta velocidade, com baixa latência e máxima largura de
banda são desejados para a construção de soluções distribuídas. Estes por sua vez devem
atender requisitos como escalabilidade, facilidade de atualização, alta disponibilidade e
bom relacionamento na relação custo/desempenho.
No artigo “A Network Interface Controller Chip for High-Performance
Computing with Distributed Pcs”, Watanabe et al. (2007) afirma que a maioria dos
clusters de alto desempenho utilizam soluções SAN (System Area Network), como o
padrão aberto chamado Myrinet. Este padrão provê alto desempenho e comunicação
eficiente de pacotes de rede, com uma boa relação custo/desempenho. Porém para
conectar computadores que estão posicionados a longas distâncias no andar de um
prédio ou mesmo ao longo de um edifício, esta solução se torna inadequada. Por outro
lado a utilização da Ethernet e do protocolo TCP/IP, em pequenas redes locais, tornou-
se muito popular como camada de interconexão entre computadores, principalmente
após a popularização do Beowulf cluster.
Os esforços na eliminação de gargalos de comunicação e a maximização da
velocidade de transmissão estão presentes em tecnologias como Memory Channel,
Quadrics e o Infiniband. Não iremos abordar este assunto com maior aprofundamento,
porém, a seguir, encontra-se um resumo de como funcionam estas tecnologias.

30
• Memory Channel: segundo Dantas (2005), a abordagem conhecida como
Memory Channel fornece até 100Mb/s de velocidade de transferência e a
distância física pode ser de até 10 (dez) metros. Esta tecnologia usa um switch
externo e placas específicas para realizar a sincronização dos dados.
• Quadrics ou QsNET: a topologia desta rede é do tipo Fat-Tree, sendo possível
expandir a rede a milhares de dispositivos de comutação. A taxa de transferência
pode atingir a centenas de Mb/s e fornece baixa latência. Utiliza uma interface
de rede programada chamada Elan [Dantas 2005].
• Infiniband: é uma especificação para protocolos de comunicação gerida pelo
grupo Infiniband Trade Association (http://www.infinibandta.org). Este grupo é
composto por fornecedores líderes de mercado tais como HP, IBM, Intel,
Lellanox, Oracle, Qlogic e System Fabric Works. Este protocolo fornece uma
interface de comunicação com elevadas taxas de transferência e suporte a
endereçamento para até 64.000 dispositivos, suportando failover e QoS (Quality
of Service).

2.6. Clusters e Grids


Os clusters são aglomerados de computadores, interconectados através de uma mesma
rede, que utilizam sistemas e componentes de hardwares especializados, fornecendo ao
usuário final uma “imagem” unificada do sistema. Neste arranjo, cada componente do
aglomerado é chamado de nó e geralmente existe um deles responsável por controlar e
gerenciar os demais, denominado mestre. Para que sejam eficientes, a camada de
comunicação deve ser rápida e confiável o suficiente para maximizar a utilização dos
processadores e não gerar perdas de dados.
Durante o projeto e implementação destes aglomerados, são estudadas
características importantes para garantir a confiabilidade do sistema. Aspectos como
escalabilidade, tolerância a falhas, disponibilidade e a interdependência entre estes
fatores são reunidas em torno da meta de construir um sistema que seja aderente ao
propósito final, com menor custo de processamento/hora.
Há disponível no mercado clusters com as mais diversas finalidades, porém os
mais comuns são os relacionados a seguir:
• alto desempenho: utilizados para executar aplicações que requerem grande
quantidade de processamento como em aplicações que envolvem cálculos
numéricos, simuladores e programas científicos em geral;
• alta disponibilidade: são clusters construídos com aplicações auto gerenciáveis,
que conseguem identificar falhas e proteger o sistema garantindo o uptime dos
aplicativos em execução;
• balanceamento de carga: composto de mecanismos que gerenciam a carga de
trabalho entre os nós do agrupamento, escalonando de forma controlada, para
não sobrecarregar somente alguns recursos. Conta também com recursos que
identificam a indisponibilidade e falhas dos nós gerenciados.
Computadores de múltiplos domínios, trabalhando em torno de uma mesma
tarefa com o objetivo de finalizar-la o mais rápido possível são classificados como Grid.

31
Os Grids utilizam middlewares que dividem uma grande tarefa em pequenas partes
distribuindo entre os nós participantes e consolidando os resultados.
Um dos mais bem-sucedidos middlewares para computação em Grid é o projeto
open source encabeçado pela Universidade da Califórnia, nos EUA. O Berkeley Open
Infrastructure for Network Computing, mais conhecido pelo seu acrônimo BOINC. O
BOINC é um software para computação voluntária utilizado em importantes projetos
como o SETI@home, que analisa ondas de rádio provenientes do espaço sideral em
busca de vidas extraterrestres. O CERN (European Organization for Nuclear Research)
também utiliza este software para analisar os dados gerados pelo Grande Colisor de
Hádrons , o LHC. Há ainda projetos específicos como o World Community Grid e o
Folding@Home, este último da universidade de Standford, que se dedicam a buscar
cura para doenças.

2.7. Métricas em Computação Paralela


Em um primeiro contato com a computação paralela, podemos nos deixar levar pela
errônea ideia de que ao dividir o trabalho em n unidades de processamento, os ganhos
desempenho seriam proporcionalmente em n vezes. É importante ressaltar que isto nem
sempre é possível. Navaux (2003) relaciona os grandes desafios na área de
processamento de alto desempenho, que explicam o motivo pelo qual nem sempre é
possível obter tal resultado. Os mesmos estão pautados em 4 (quatro) aspectos:
arquiteturas paralelas, gerenciamento das máquinas, linguagens mais expressivas que
consigam extrair o máximo de paralelismo e finalmente uma maior concorrência nos
algoritmos.
Para nos auxiliar a mensurar os ganhos ao paralelizar algoritmos seriais,
podemos utilizar a métrica denominada Speedup. Em computação paralela, o Speedup é
utilizado para conhecer o quanto um algoritmo paralelo é mais rápido que seu
correspondente sequencial. Pode ser obtido pela seguinte equação:
Tempo serial
Speedup=
Tempo Paralelo
O resultado deve variar entre 0 (zero) – quanto mais próximo a zero, maiores
foram os ganhos - e 1 (um). Caso seja superior a 1 (um), o algoritmo paralelo é menos
eficiente que o serial e precisa ser avaliado para a remoção de gargalos, ou ainda, para
apurar se foram escolhidas as melhores abordagens durante o projeto do seu código.
Objetivando, portanto, estimar teoricamente os ganhos ao se paralelizar todo ou
parte de um código, foi anunciada a lei de Amdahl, a qual assume que o desempenho do
algoritmo fica limitado pela fração de tempo das partes paralelizáveis durante sua
execução, sendo obtido a partir da equação:
1
Speedup=
Fração Sequencial do Programa
( Fração Sequencial do Programa+(1− ))
Número de Processadores
Alguns cientistas consideram o Speedup obtido pela lei de Amdahl uma
abordagem pessimista, pois não avalia a complexidade e o tamanho do problema a ser
tratado. Diante disto, foi anunciada uma segunda lei, que leva em conta tais fatores,
segundo a equação:

32
Speedup=Núm.processadores−Fração sequêncial do programa( Núm.processadores−1)
Esta lei é conhecida como lei de Gustafon-Barsis.

2.8. O MPI
Durante a década de 90, foram produzidas duas especificações que unificaram os
trabalhos dos participantes do MPI Forum (http://www.mpi-forum.org) na área de
processamento paralelo e distribuído. Este trabalho foi encabeçado por um grupo
formado por cerca de 60 pessoas provenientes de mais de 40 organizações dos Estados
Unidos e Europa, sendo fortemente influenciado pelos resultados até então alcançados
nos grupos do IBM T.J. Watson Research Center, Intel's NX/2 , Express, nCUBE's
Vertex, p4 e o PARMACS. Outras importantes contribuições vieram também do
Zipcode, Chimp, PVM, Chameleon e PICL.
A primeira versão – MPI-1 - foi publicada no ano de 1994 contando com os
requisitos base necessários para o padrão de troca de mensagens. Os pontos mais
complexos foram deixados para a versão MPI-2, lançada posteriormente em 1997
[Mattson et al. 2010] .
Os trabalhos mais recentes do MPI Forum remontam aos anos de 2008 e 2009,
tendo como diretrizes a correção de bugs, a compilação das duas especificações – MPI-1
e MPI-2 - em um único documento e a publicação de revisões minor: MPI-2.1 e MPI-
2.2. A última atualização aconteceu em setembro de 2012, quando o grupo publicou o
maior grupo de atualizações no padrão, incluindo novas extensões, a remoção de
bindings obsoletos para o C++ e o suporte ao FORTRAN 2008. Este último release foi
nomeado como MPI-3.0.
Apesar de não ser uma norma homologada por institutos como IEEE, IETF, o
MPI é “De facto” um padrão para arquiteturas de memória distribuída, escrito e
ratificado pelo MPI Forum. A idéia central do MPI consiste em prover rotinas de
sincronização e controle processos, além da distribuição e consolidação dos dados entre
os computadores interconectados, utilizando para isto o paradigma de troca de
mensagens.
O modelo da API do MPI, entrega ao programador uma camada de abstração,
altamente portável, entre o sistema operacional/tecnologias de comunicação e a
aplicação, permitindo escalar a execução do programa entre os computadores da rede,
com o uso de suas memórias e poder de processamento, baseado no padrão de divisão e
conquista. Por ser uma camada de alto nível, é possível utilizar o mesmo programa em
uma grande variedade de computadores que estejam interconectados. A API é muito
adequada a programas de propósito geral desenhados para sistemas SIMD e MIMD.
O padrão tem como foco auxiliar a todos que precisem ou desejem criar
aplicativos portáveis e paralelos em Fortran e C, fornecendo uma interface simples que
atenda desde soluções menos sofisticadas até as mais avançadas, voltadas para o alto
desempenho, como as disponíveis em computadores massivamente paralelos.
Cabe enfatizar que o MPI é uma especificação. No entanto, há disponíveis no
mercado implementações livres e pagas. Podemos relacionar no modelo pago o Intel
MPI, HP MPI e o MATLab MPI. Já as implementações open source mais utilizadas são

33
o Open MPI e o MPICH. Fabricantes de supercomputadores costumam incluir features e
ferramentas específicas que visam maximizar o desempenho em suas máquinas.
Apesar de todas as facilidades do padrão, a identificação das zonas paralelas
(áreas do código que podem ser executadas simultaneamente a outras tarefas) e o
dimensionamento de carga entre os computadores participantes, ficam a cargo do
desenvolvedor e devem ser explicitadas no programa. Uma análise prévia do problema a
ser tratado, irá auxiliá-lo nesta tarefa.
Como o objetivo é o aumento de desempenho, deve-se ter em mente o projeto de
um programa que realiza a menor troca de mensagens possível, visando anular e/ou
reduzir o impacto do tempo despendido na distribuição e consolidação dos dados, no
tempo total de execução. Podemos relacionar como exemplos os Hipercubos e Meshes,
que são formas de interconexão que visam reduzir e otimizar o processamento. Não
iremos abordar este tema aqui por ser tratar de um tópico complexo para quem está
começando a explorar computação paralela.
Para finalizar a apresentação do padrão, vamos conhecer alguns conceitos
importantes inerentes a API, os quais nos ajudarão a compreender as funções
disponíveis e como funciona o MPI. Estes são:
• Processo: é o módulo executável, ou seja, seu programa, que pode ser dividido
em N partes, e executado em uma ou mais máquinas;
• Grupo: é o conjunto de processos. No MPI a constante MPI_COMM_WORLD
armazena o comunicador de todos os processos definidos na aplicação MPI;
• Rank: o controle de execução do programa em MPI depende diretamente da
correta identificação do processador no grupo de trabalho. Esta identificação é
um número inteiro que varia de 0 a N-1 processos. A função MPI_Comm_rank
determina qual é o identificador de cada processo dentro do comunicador;
• Comunicador: é o componente que representa o domínio de uma comunicação
em uma aplicação MPI;
• Buffer de Aplicação: é o espaço reservado em memória para armazenar os dados
das mensagens que um processo necessita enviar ou receber, gerenciado pela
aplicação;
• Buffer de Sistema: é o espaço reservado em memória pelo sistema para o
gerenciamento de mensagens.

2.8.1 Estrutura de um código MPI


Antes de avançarmos nas funções que compõe a API, precisamos compreender alguns
aspectos estruturais no código. Na declaração de dependências, é obrigatório a inclusão
do cabeçalho mpi.h em todos os arquivos que utilizarem algum recurso do MPI. Este
cabeçalho contém as definições de funções e constantes necessários durante o
desenvolvimento e compilação do seu programa. Todas as chamadas MPI devem estar
entre o MPI_Init e o MPI_Finalize, conforme a seguir(Figura 2.6).

34
Figura 2.6. Estrutura de um código em C/MPI.

O MPI emprega uma consistente padronização, que ajuda o desenvolvedor a


identificar facilmente métodos e tipos da API. Todos os identificadores possuem o
prefixo “MPI_”. Tipos e constantes estão em letras maiúsculas (Ex. MPI_SHORT) e as
funções estão definidas com a primeira letra em maiúscula e as demais letras em
minúsculas. (Ex. MPI_Send).
Para o tratamento de exceções, a biblioteca conta com um manipulador de erros
próprio. Caso ocorra algum problema durante a execução, o mesmo é responsável por
sinalizar a ocorrência para seu aplicativo e abortar as chamadas MPI .
Devido ao suporte a várias linguagens, foi necessário criar tabelas de
equivalência de tipos de dados entre a API e as linguagens. A seguir, a tabela de
equivalência para o C (Tabela 2.1):
Tabela 2.1. Equivalência de tipos de dados

Tipo de Dados do MPI Tipo de Dados do C

MPI_CHAR signed char

MPI_SHORT signed short int

MPI_INT signed int

MPI_LONG signed long int

MPI_UNSIGNED_CHAR unsigned char

MPI_UNSIGNED_SHORT unsigned short int

MPI_UNSIGNED unsigned int

MPI_UNSIGNED_LONG unsigned long int

35
MPI_FLOAT float

MPI_DOUBLE double

MPI_LONG_DOUBLE long double

MPI_PACKED

MPI_BYTE

2.8.2 MPI_Init
Este método inicializa o ambiente de execução do MPI, sincronizando os processos
entre os computadores participantes e deve ser invocado uma única vez durante toda a
execução do seu aplicativo. Caso contrário, o MPI irá sinalizar com o erro
MPI_ERR_OTHER. A assinatura do método encontra-se a seguir:

int MPI_Init( int *argc, char ***argv );


argc
Ponteiro indicando o número de argumentos
argv
Ponteiro do vetor com os argumentos

Listagem 2.1. MPI_Init

Devemos assegurar que a chamada seja realizada por apenas uma Thread e que
esta mesma Thread invoque, ao final do processamento, o método MPI_Finalize.

2.8.3 MPI_Finalize
Finaliza o ambiente de execução do MPI, liberando os recursos utilizados durante o
processamento. Deve ser invocado sob a mesma Thread que executou o MPI_Init. Este
método não possui argumentos.

2.8.4 Envio e recebimento de dados síncrono: MPI_Send e MPI_Recv


O MPI disponibiliza várias rotinas para realizar as operações de envio e recebimento de
mensagens entre os processadores, enquanto a de envio é feita pela função MPI_Send, a
de recebimento é pelo MPI_Recv. Estes dois métodos realizam a operação de envio e
recebimento de mensagens de forma síncrona, ou seja, aguarda a confirmação de
recebimento da mensagem para passar para a próxima instrução. As definições
encontram-se a seguir:

int MPI_Send(void *buf, int count, MPI_Datatype datatype, int


dest,int tag, MPI_Comm comm);
buf
Endereço do buffer de dados a ser enviado.
count
Número de elementos a ser enviado (número inteiro e não negativo).

36
datatype
Tipo do dado.
dest
Rank do destinatário.
tag
Identificador para a mensagem (número inteiro).
comm
Comunicador. Em SIMD (MPI_COMM_WORLD), Em MIMD (O comunicador criado pela
função MPI_Comm_create)

Listagem 2.2. MPI_Send

int MPI_Recv(void *buf, int count, MPI_Datatype datatype,int source,


int tag, MPI_Comm comm, MPI_Status *status);
buf
Endereço do buffer para receber os dados.
count
Número de elementos a ser recebido (número inteiro e não negativo).
datatype
Tipo do dado.
source
Rank do remetente.
tag
Identificador para a mensagem (número inteiro).
comm
Comunicador. Em SIMD (MPI_COMM_WORLD), Em MIMD (O comunicador criado pela
função MPI_Comm_create)
Status
Status da mensagem

Listagem 2.3. MPI_Recv

2.8.5 Envio e recebimento de dados assíncrono: MPI_Isend e MPI_Irecv


O MPI_Isend e o MPI_Irecv fornecem a funcionalidade de envio e recebimento
assíncrono, respectivamente. Como só o comportamento é modificado, é possível
combinar os métodos MPI_Send/MPI_Recv com os métodos MPI_Isend/MPI_Irecv.

int MPI_Isend(void *buf, int count, MPI_Datatype datatype, int dest,


int tag, MPI_Comm comm, MPI_Request *request);
buf
Endereço do buffer de dado a ser enviado.
count
Número de elementos a ser enviado (número inteiro e não negativo).
datatype
Tipo do dado.
dest
Rank do destinatário.
tag
Identificador para a mensagem (número inteiro).
comm
Comunicador. Em SIMD (MPI_COMM_WORLD), Em MIMD (O comunicador criado pela
função MPI_Comm_create)

37
request
Solicitação de envio. Utilizado pelas funções de bloqueio como MPI_Wait para assegurar a
conclusão do processamento.

Listagem 2.4. MPI_Isend

int MPI_Irecv(void *buf, int count, MPI_Datatype datatype,int source,


int tag, MPI_Comm comm, MPI_Request *request);
buf
Endereço do buffer para receber os dados.
count
Número de elementos a ser recebido (número inteiro e não negativo).
datatype
Tipo do dado.
source
Rank do remetente.
tag
Identificador para a mensagem (número inteiro).
comm
Comunicador. Em SIMD (MPI_COMM_WORLD), Em MIMD ( O comunicador criado pela
função MPI_Comm_create)
request
Solicitação de recebimento. Utilizado pelas funções de bloqueio como MPI_Wait para assegurar
a conclusão do processamento.

Listagem 2.5. MPI_Irecv

2.8.6 MPI_Wait
Ao realizar operações assíncronas, podemos nos deparar com situações de dependência (
dados, instruções, entre outros) onde é necessário assegurar a conclusão dos mesmos
antes de executar a próxima instrução. Para solucionar tais questões o MPI fornece
funções como o MPI_Wait.

int MPI_Wait(MPI_Request *request, MPI_Status *status);

request
Identificador da requisição a ser bloqueada.
status
Retorna a informação sobre a situação da operação. Para testar o status utilize a função
MPI_Test

Listagem 2.6. MPI_Wait

2.8.7 Comunicações Coletivas


Até o momento, foram apresentadas rotinas que fazem a comunicação entre dois
processos específicos, denominados ponto-a-ponto. Adicionalmente a estas funções, o
MPI provê suporte a operações que devem ser realizadas simultaneamente em mais de

38
dois processos de um grupo de trabalho, especificados através do contexto - para
arquiteturas SIMD (MPI_COMM_WORLD), já em MIMD (o comunicador criado pela
função MPI_Comm_create).
As operações mais comuns nas comunicações coletivas são as que realizam
sincronização, distribuição de dados (Broadcast) e finalmente, as reduções (Reduction)
para operações de consolidação de dados, como operações de soma por exemplo.

2.8.8 MPI_Barrier
O MPI_Barrier define um ponto de sincronização entre todos os processos participantes
da comunicação coletiva, isto é, o código não pode prosseguir enquanto todos não
estiverem no sincronizados no mesmo ponto.

int MPI_Barrier(MPI_Comm comm);

comm
Comunicador. Em SIMD (MPI_COMM_WORLD), Em MIMD (O comunicador criado pela
função MPI_Comm_create)

Listagem 2.7. MPI_ Barrier

2.8.9 MPI_Bcast
A distribuição de uma mensagem para todos os processos do grupo é realizado pela
função MPI_Bcast.

int MPI_Bcast(void *buffer, int count, MPI_Datatype datatype,int


root, MPI_Comm comm);
buf
Endereço do buffer de dados a ser enviado.
count
Número de elementos a ser enviado (número inteiro e não negativo).
datatype
Tipo do dado.
root
Rank do destinatário.
comm
Comunicador. Em SIMD (MPI_COMM_WORLD), Em MIMD (O comunicador criado pela
função MPI_Comm_create)

Listagem 2.8. MPI_ Bcast

2.8.10 MPI_Reduce
Para a consolidação dos resultados do processamento em comunicações coletivas, a
função MPI_Reduce fornece vários tipos de operações (Tabela 2.2).
Tabela 2.2. Operações do MPI_Reduce no MPI

ID Operação

MPI_MAX Maior número

39
MPI_MIN Menor número

MPI_SUM Soma

MPI_PROD Produto

MPI_LAND Conjunção lógica E

MPI_BAND Conjunção lógica bit a bit E

MPI_LOR Conjunção lógica OU

MPI_BOR Conjunção lógica bit a bit OU

MPI_LXOR Disjunção lógica

MPI_BXOR Disjunção lógica bit a bit

MPI_MAXLOC Máximo e sua localização

MPI_MINLOC Mínimo e sua localização

int MPI_Reduce(void *sendbuf, void *recvbuf, int count,MPI_Datatype


datatype, MPI_Op op, int root, MPI_Comm comm)

sendbuf
Endereço do buffer de envio.
recvbuf
Endereço do buffer de recebimento.
count
Número de elementos a ser enviado (número inteiro e não negativo).
datatype
Tipo do dado.
op
Identificador da operação de redução.
root
Rank do processo que realizará a operação de redução.
comm
Comunicador. Em SIMD (MPI_COMM_WORLD), Em MIMD (O comunicador criado pela
função MPI_Comm_create)

Listagem 2.9. MPI_Reduce

2.8.11 MPI_Scatter e MPI_Gather


Para a distribuição e recolhimento de mensagens contendo pedaços de dados de mesmo
tamanho, o MPI fornece dois métodos: o MPI_Scatter e o MPI_Gather. Estas duas
funções são muito úteis em operações envolvendo álgebra linear, como multiplicação de
matrizes, por exemplo. O MPI_Scatter é responsável pela distribuição dos dados, já o
MPI_Gather pelo recolhimento.

int MPI_Scatter(void *sendbuf, int sendcount, MPI_Datatype

40
sendtype,void *recvbuf, int recvcount, MPI_Datatype recvtype, int
root,MPI_Comm comm)
sendbuf
Endereço do buffer para envio dos dados.
sendcount
Número de elementos a ser enviado (número inteiro e não negativo).
sendtype
Tipo do dado.
recvcount
Número de elementos no buffer de recebimento (número inteiro e não negativo).
recvtype
Tipo do dado.
root
Rank do processo de envio.
comm
Comunicador. Em SIMD (MPI_COMM_WORLD), Em MIMD (O comunicador criado pela
função MPI_Comm_create)

Listagem 2.10. MPI_Scatter

int MPI_Gather(void *sendbuf, int sendcount, MPI_Datatype


sendtype,void *recvbuf, int recvcount, MPI_Datatype recvtype, int
root,MPI_Comm comm)
sendbuf
Endereço do buffer para envio dos dados.
sendcount
Número de elementos a ser enviado (número inteiro e não negativo).
sendtype
Tipo do dado.
recvcount
Número de elementos no buffer de recebimento (número inteiro e não negativo).
recvtype
Tipo do dado.
root
Rank do processo de envio.
comm
Comunicador. Em SIMD (MPI_COMM_WORLD), Em MIMD (O comunicador criado pela
função MPI_Comm_create)

Listagem 2.10. MPI_Gather

2.8.12 MPI_Allgather
Quando todos os processos precisam receber os dados coletados dos demais processos
do grupo, o MPI_Allgather deve ser utilizado. Novamente aqui os dados precisam ser
do mesmo tamanho.

int MPI_Allgather(void *sendbuf, int sendcount,MPI_Datatype


sendtype, void *recvbuf, int recvcount,MPI_Datatype recvtype,
MPI_Comm comm)
sendbuf
Endereço do buffer para envio dos dados.

41
sendcount
Número de elementos a ser enviado (número inteiro e não negativo).
sendtype
Tipo do dado.
recvbuf
Endereço do buffer para recebimento dos dados.
recvcount
Número de elementos no buffer de recebimento (número inteiro e não negativo).
recvtype
Tipo do dado.
comm
Comunicador. Em SIMD ( MPI_COMM_WORLD), Em MIMD (O comunicador criado pela
função MPI_Comm_create) .

Listagem 2.11. MPI_Allgather

2.8.13 Tipos derivados de dados.


Os mecanismos básicos de comunicação do MPI podem ser usados para enviar ou
receber sequências de elementos de mesmo tipo, que podem ser ou não contíguos em
memória. O objetivo é amortizar o custo desta operação e prover ganhos no tempo total
de execução do seu algoritmo.
Diferentemente da abordagem de declaração em tempo de desenvolvimento, no
MPI os tipos de dados são criados em tempo de execução, entre as funções MPI_Init e
MPI_Finalize. O ciclo de vida destes tipos possuem as seguintes etapas: declaração,
alocação, o uso efetivo do tipo durante a execução do programa e, finalmente, a
liberação dos recursos. Os métodos de construção destes tipos são:
• MPI_Type_contiguous: é o construtor mais simples dentre os disponibilizados
no MPI. Gera um novo tipo contínuo a partir de cópias de um tipo de dados
existente.
• MPI_Type_vector: semelhante ao MPI_Type_contiguous, porém permite a
configuração de lacunas (strides) nos deslocamentos. Há ainda a função
MPI_Type_hvector que é um MPI_Type_vector, porém definido em bytes.
• MPI_Type_indexed: gera uma matriz de deslocamentos do tipo de dados como
um mapa para o novo tipo de dados. Há ainda a sua variação em bytes:
MPI_Type_hindexed.
• MPI_Type_struct: dos tipos derivados, este é o mais genérico. O novo tipo é
formado de acordo com cada componente da estrutura de dados.
Antes de ser utilizado, é necessário informar aos processadores da comunicação
coletiva que o tipo está disponível. Esta operação é feita através da função
MPI_Type_commit. Para a liberação dos recursos alocados, a função é a
MPI_Type_free. Como o free no C, o MPI_Type_free evita o consumo de memória
desnecessário, para os tipo de dados que não são mais utilizados.
A utilização de tipos derivados é recomendada por prover uma solução portável
e elegante para o envio de dados não contíguos, maximizando a eficiência dos métodos
de envio e recebimento de dados, promovendo ganhos no tempo total de execução do
seu programa.

42
2.9. Conclusões
Neste minicurso buscamos explorar uma visão geral sobre arquiteturas paralelas e o
modelo de programação baseado no paradigma de message passing. A partir das
funções e ideias apresentadas, é possível construir códigos explorando paralelismo com
o MPI. As features mais complexas do MPI não abordadas retratam questões de
refinamento de desempenho e manipulação de arquivos de forma paralela. Estas
características podem ser conhecidas através do site do MPI-Forum( http://www.mpi-
forum.org) ou por intermédio das bibliografias listadas nas referências.
Em Computação Paralela, há ainda outras tecnologias que podem ser utilizadas
em conjunto ao MPI. Em Memória Compartilhada (Shared Memory), por exemplo, o
modelo do OpenMP fornece os mesmos benefícios de portabilidade do OpenMPI para
este tipo de arquitetura. Há ainda abordagens que exploram paralelismo em placas de
vídeo , como o modelo livre chamado OpenCL, definido pelo consórcio de empresas
chamado Khronos Group, além dos modelo proprietários propostos pela NVIDIA
(CUDA) e o OpenACC(http://www.openacc-standard.org/), encabeçado atualmente pela
PGI, Nvidia, Caps e Cray.

Referências
Chen, Yen-Kuang. (2008), “Convergence of Recognition, Mining, and Synthesis
Workloads and Its Implications”, http://ieeexplore.ieee.org/xpl/login.jsp?
tp=&arnumber=4479863&url=http%3A%2F%2Fieeexplore.ieee.org%2Fxpls
%2Fabs_all.jsp%3Farnumber%3D4479863, Maio.
Dantas, Mario. (2005), Computação Distribuída de Alto Desempenho, Axcel, 1º edição.
De Rose, César A. F. Navaux, Phillippe O. A. (2005), Arquiteturas Paralelas, Bookman,
1º edição.
Gebali, Fayez. (2011), Algorithms and Parallel Computing, Wiley, 1º edição.
Hennesy. John L. Patterson, David A. (2012), Computer Architecture, Morgan
Kaufamann, 5º edição.
Kirk, David B. Hwu, Wen-mei W. (2010), Programming Massively Parallel Processors,
Morgan Kaufmann, 1º edição.
Martin, Milo M. K. Hill,Mark D. Sorin,Daniel J. (2012), “Why on-chip cache coherence
is here to stay”, http://doi.acm.org/10.1145/2209249.2209269, Julho
Mattson, T.G, Sanders. B.A., Massingill, B.L. (2010), Patterns for Parallel
Programming. Addison-Wesley, 1º edição.
Mishra, Bhabani Shankar. and Dehuri, Satchidananda (2011). “Parallel Computing
Environments: A Review”., http://tr.ietejournals.org/article.asp?issn=0256-
4602;year=2011;volume=28;issue=3;spage=240;epage=247;aulast=Mishra;t=6, Maio
MPI Forum. (2012), “MPI-3.0 Standard Specification”, http://www.mpi-
forum.org/docs/mpi-3.0/mpi30-report.pdf, Setembro.

43
Peiqiang, L. Zeng, Y. Kotoulas, S. Urbani, J. and Zhong, N. (2009) “The Quest for
Parallel Reasoning on the Semantic Web”, http://dx.doi.org/10.1007/978-3-642-
04875-3_45, Novembro.
Pitt-Francis, J. and Whiteley, J. (2012), An Introduction to Parallel Programming Using
MPI - Guide to Scientific Computing in C++ ,Springer, 1º edição
Quammen, Cory. (2005). “Introduction to programming shared-memory and distributed-
memory parallel computers”, http://doi.acm.org/10.1145/1144382.1144384 , Outubro
Quinn, Michael J. (2003), Parallel Programming in C with MPI and OpenMP, Mc Graw
Hill, 1º edição.
Watanabe, K. Otsuka, T. Tsuchiya, J. Nishi, H. Yamamoto, J. Tanabe, N. Kudoh, T. and
Amano, H. (2007), “A Network Interface Controller Chip for High Performance
Computing with Distributed PCs, Parallel and Distributed Systems”,
http://ieeexplore.ieee.org/stamp/stamp.jsp?
tp=&arnumber=4288127&isnumber=4288116, Setembro.

44
Introdução​ ​ao​ ​CUDA
Material​ ​elaborado​ ​por​ ​Davi​ ​Conte.

O objetivo deste material é que o aluno possa iniciar seus conhecimentos em


programação paralela, entendendo a diferença da execução de forma sequencial e de
forma concorrente, assim como os ganhos de desempenho refletidos desses modelos. Para
isso será apresentada a tecnologia por trás do modelo de programação em CUDA. Serão
discutidos os conceitos básicos da arquitetura de uma placa de vídeo, o funcionamento da
GPU e computação em GPU, conhecimentos necessários para realizar a compreensão de
CUDA.

1. A​ ​Placa​ ​de​ ​Vídeo

Antes de começarmos a falar sobre CUDA em si, é necessário entendermos o que é


placa de vídeo e GPU (Graphics Processing Unit). Primeiramente, para ter uma breve
introdução​ ​do​ ​que​ ​é​ ​a​ ​placa​ ​de​ ​vídeo,​ ​assista​ ​o​ ​vídeo​ ​referenciado​ ​no​ ​link​ ​abaixo.

→​​ ​https://www.youtube.com/watch?v=Cqht_EfXDLk&t=193s

Continuando, o principal elemento de uma placa de vídeo que vamos estudar é a


Graphics Processing Unit, também conhecida como GPU. Este componente se comporta
como​ ​um​ ​processador​ ​dedicado​ ​especialmente​ ​para​ ​a​ ​renderização​ ​de​ ​gráficos.

Figura​ ​1.​ ​GPU​ ​exposta​ ​em​ ​uma​ ​placa​ ​de​ ​vídeo​ ​[1]

A GPU fica encarregada pelo processamento de cada pixel da tela, gerando, assim,
a imagem proveniente de de um alto número de operações. Por isso, a GPU possui
diversos núcleos que são como pequenos processadores (diferentes de processadores de
propósito geral como os desenvolvidos pela Intel para Notebooks ou Desktops). A Figura 2
ilustra​ ​a​ ​diferença​ ​dos​ ​múltiplos​ ​cores​ ​(núcleos)​ ​de​ ​uma​ ​CPU​ ​e​ ​os​ ​milhares​ ​de​ ​uma​ ​GPU.

Figura​ ​2.​ ​As​ ​placas​ ​de​ ​vídeo​ ​têm​ ​milhares​ ​de​ ​núcleos​ ​para​ ​processar​ ​cargas​ ​em​ ​paralelo​ ​[2]

2.​ ​Programação​ ​Paralela

Muitas vezes quando temos uma tarefa muito complexa a ser feita, podemos dividi-la
em partes menores que possam ser mais simples de serem resolvidas. A programação
paralela ou concorrente aplica esse conceito aos processadores em um computador. Um
processador executa uma única instrução de código por vez, portanto um computador com
diversos núcleos pode executar diversas instruções ou operações simultaneamente,
resolvendo problemas de menor complexidade paralelamente, ou seja, em um mesmo
instante​ ​de​ ​tempo.
Tradicionalmente, os softwares são construídos em computação serial ou
sequencial, onde o problema é dividido em uma série de instruções que são executadas
sequencialmente, uma após a outra, em um único processador, onde somente uma
instrução pode ser executada em um dado intervalo de tempo. Na computação paralela,
existe o uso simultâneo de múltiplos recursos computacionais no intuito de resolver
determinado problema. Desta forma, os problemas são divididos em partes menores que
podem ser resolvidas concorrentemente, sendo que cada parte é subdividida em uma série
de instruções, executadas simultaneamente em diferentes processadores, coordenadas por
um​ ​mecanismo​ ​de​ ​controle​ ​global​ ​[3].
A programação concorrente trata-se de um paradigma que permite a implementação
de software com múltiplas tarefas independentes, ainda que em máquinas com um único
núcleo de processamento, onde estas atividades disputam recursos computacionais,no
intuito​ ​de​ ​solucionar​ ​um​ ​problema​ ​específico.
O modelo de programação paralela permite ganhos significativos em critérios
de tempo de execução, quando comparados com soluções implementadas por meio de
programação​ ​ ​serial​ ​que​ ​são​ ​refletidos​ ​no​ ​tempo​ ​final​ ​de​ ​execução.
A Figura 3 mostra a partição de um problema, que pode ser a implementação de um
algoritmo, em quatro tarefas cujas instruções são executadas paralelamente por diferentes
CPUs.
Figura​ ​3.​ ​Divisão​ ​de​ ​tarefas​ ​de​ ​um​ ​problema​ ​entre​ ​as​ ​CPUs.

Considerando programação concorrente, a GPU, por conter diversos processadores,


se torna um ambiente onde pode ocorrer grande paralelização de processamento de dados,
o que nos leva à computação que pode ser realizada de forma paralela dentro dos núcleos
de uma GPU, apresentando melhora na performance de desempenho. A Figura 4
demonstra que parte do código de uma aplicação pode ser executada de forma paralela em
uma GPU, como por exemplo um laço de repetição com iterações definidas. Embora a
porcentagem de código executada em GPU seja pequena, o aumento de performance é
significativo comparado ao desempenho do código executado inteiramente de forma
sequencial.

Figura​ ​4.​ ​Aceleração​ ​de​ ​código​ ​utilizando​ ​GPU​ ​[2]

Para​ ​maior​ ​compreensão​ ​desse​ ​assunto,​ ​temos​ ​o​ ​próprio​ ​site​ ​da​ ​NVIDIA​ ​(produtora
de​ ​placas​ ​de​ ​vídeo​ ​e​ ​proprietária​ ​do​ ​CUDA)​ ​explicando​ ​sobre​ ​computação​ ​em​ ​aceleradores
gráficos​ ​(GPU),​ ​seguindo​ ​para​ ​o​ ​link​ ​abaixo.
→​http://www.nvidia.com.br/object/what-is-gpu-computing-br.html

3.​ ​CUDA

CUDA (Compute Unified Device Architecture) é uma plataforma de computação


paralela e um modelo de programação criados pela NVIDIA. Ela permite aumentos
significativos de performance computacional ao aproveitar a potência da unidade de
processamento​ ​gráfico​ ​(GPU)​ ​para​ ​o​ ​processar​ ​dados.
O modelo de programação CUDA utiliza as linguagens C, C++ ou Fortran, sendo
necessário possuir uma placa de vídeo da NVIDIA para poder utilizar a linguagem.
Recomenda-se a utilização de CUDA quando uma parte menor do processamento pode ser
replicada e executada paralelamente em diversos núcleos. Isso porque os núcleos da GPU
são​ ​menos​ ​poderosos,​ ​porém​ ​mais​ ​numerosos.
Para maior detalhamento sobre CUDA, recomenda-se a leitura do seguinte material
proposto​ ​pela​ ​própria​ ​NVIDIA,​ ​desenvolvedora​ ​do​ ​CUDA.

→​ ​http://www.nvidia.com.br/object/cuda_home_new_br.html

O gráfico da Figura 5, a seguir, demonstra a performance da execução de um


algoritmo de multiplicação de matrizes sequencial (em uma CPU) e em paralelo (GPU)
implementado com CUDA. É possível perceber a grande diferença de tempo de execução
principalmente nas matrizes de maior tamanho (no gráfico: matrix size). Enquanto no
sequencial a diferença da ordem (tamanho) da matriz influencia fortemente no tempo de
execução, na execução paralela esse crescimento do tempo não é tão grande. O tempo no
gráfico​ ​é​ ​medido​ ​em​ ​milissegundos​ ​(ms).
Figura​ ​5.​ ​Multiplicação​ ​de​ ​matrizes​ ​paralelo​ ​e​ ​sequencial.​ ​[5]

4.​ ​Programação​ ​em​ ​CUDA

O objetivo deste capítulo é introduzir ao aluno os códigos em CUDA, apresentando


seu compilador, funções específicas e exemplos de código. Este capítulo foi escrito
baseado no capítulo 3 do livro “Cuda by example” escrito por Jason Sanders e Edward
Kandrot​ ​[4],​ ​abordando​ ​diretamente​ ​os​ ​seguintes​ ​temas:
● Chamada​ ​de​ ​Kernel​ ​(__global__)
● Device​ ​and​ ​host
● Exemplo​ ​HELLO,​ ​WORLD​ ​em​ ​C​ ​+​ ​CUDA
● Kernel<<<1,1>>>();
● Passagem​ ​de​ ​parâmetros
● Funções​ ​básicas​ ​e​ ​utilização​ ​(cudaMalloc(),​ ​cudaMemcpy(),​ ​cudaFree())
● Exemplo​ ​Soma​ ​de​ ​vetores

4.1.​ ​Um​ ​primeiro​ ​programa

De acordo com as leis da computação, vamos iniciar a programação em CUDA com


um bom código de Hello World! Uma observação importante é que o compilador de CUDA
interpreta as linguagens C, C++ e Fortran naturalmente, ou seja, podemos compilar um
programa de Hello World somente utilizando a linguagem C utilizando compilador CUDA.
Porém, se for compilado e executado um código em C puro, mesmo com o compilador de
CUDA, ele não será executado na GPU, cuja terminologia será usada como ​device​, mas
será executado na CPU, cuja terminologia será usada como ​host​, pois para executar em
GPU são necessários comandos específicos de CUDA. Um programa em CUDA tem a
extensão .cu e seu compilador é o ​nvcc​. Para compilar um código desenvolvido em CUDA,
basta​ ​utilizar​ ​o​ ​seguinte​ ​comando​ ​para​ ​um​ ​programa​ ​.cu:
Para um código ser executado pelo ​device (GPU), é necessário fazer parte de uma função
que​ ​tipicamente​ ​é​ ​chamada​ ​de​ ​kernel​.

4.1.1.​ ​A​ ​Chamada​ ​de​ ​Kernel

Uma ​chamada de ​Kernel nada mais é do que a chamada da função que será
executada pela GPU de forma paralela. Essa função precisa ser marcada para que o
compilador (nvcc) saiba que a função é um código para a GPU. Observe nas imagens
abaixo a diferença entre um programa “Hello, World” tradicional em C e outro “Hello, World”
com​ ​uma​ ​chamada​ ​de​ ​Kernel​ ​(execução​ ​na​ ​GPU).

Figura​ ​5.​ ​Hello​ ​World​ ​tradicional​ ​em​ ​C.

Figura​ ​6.​ ​Hello​ ​World​ ​com​ ​função​ ​Kernel​ ​executada​ ​na​ ​GPU.

O​ ​primeiro​ ​código,​ ​responde​ ​com​ ​“Hello,​ ​World”​ ​da​ ​CPU,​ ​enquanto​ ​que​ ​o​ ​segundo
responde​ ​da​ ​GPU.​ ​Estes​ ​dois​ ​códigos​ ​possuem​ ​duas​ ​diferenças​ ​notáveis:
● Uma​ ​função​ ​chamada​ ​Kernel​ ​qualificada​ ​com​ _ ​ _global__;​ ​e
● A​ ​chamada​ ​para​ ​esta​ ​função​ ​utilizando​ ​<<<1,1>>>.

O mecanismo da marcação __global__ em uma função alerta o compilador que a


função deve ser compilada para executar no ​device (GPU) ao invés do ​host (CPU). No
exemplo acima, o compilador (nvcc) envia a função ​kernel() para outro compilador que
gerencia sua execução nos núcleos da GPU enquanto que a função ​main() é executada na
CPU.​ ​A​ ​utilização​ ​de​ ​<<<1,1>>>​ ​para​ ​chamadas​ ​de​ ​kernel​ ​será​ ​explicada​ ​posteriormente.

4.1.2.​ ​Passagem​ ​de​ ​Parâmetros

A função ​kernel​, por mais que seja executada na GPU, também pode conter
parâmetros em sua chamada, que falaremos a seguir. Considere o código em CUDA a
seguir​ ​que​ ​será​ ​tomado​ ​como​ ​exemplo.

Figura​ ​7.​ ​Adição​ ​em​ ​CUDA.

Você poderá perceber diversas alterações, novas linhas e comandos nesse trecho
de​ ​código,​ ​porém​ ​essas​ ​mudanças​ ​demonstram​ ​dois​ ​conceitos:
● Podemos​ ​passar​ ​parâmetros​ ​para​ ​a​ ​função​ k​ ernel​ ​como​ ​qualquer​ ​outra​ ​função;​ ​e
● Precisamos alocar memória para realizar qualquer atividade no ​device​, como
retornar​ ​valores​ ​ao​ ​host​.

Podemos concluir que uma chamada de ​kernel funciona da mesma maneira que
uma função comum no padrão C. Podemos passar os parâmetros da mesma forma
tradicional e a compilação realiza a parte complexa da passagem dos parâmetros do ​host
para​ ​device​.

4.1.3.​ ​Alocando​ ​memória​ ​com​ ​cudaMalloc()

Um detalhe interessante da implementação da Figura 7 é a alocação de memória


usando ​cudaMalloc(). Esta chamada é semelhante ao ​malloc() do padrão em C, porém
indica ao compilador de CUDA a alocação de memória no ​device (GPU). Este comando é
necessário para alocar espaço na memória para variáveis que serão utilizadas na chamada
de​ ​kernel​ ​(processamento​ ​da​ ​GPU).​ ​Os​ ​argumentos​ ​desta​ ​chamada​ ​são​ ​os​ ​seguintes:
1- um ponteiro para o ponteiro que deseja guardar o endereço do novo espaço de memória
alocado.
2-​ ​Tamanho​ ​da​ ​alocação​ ​que​ ​deseja​ ​realizar.

Exemplo​ ​dos​ ​parâmetros​ ​de​ ​cudaMalloc()​.

O ponteiro de endereço de memória que é passado em ​cudaMalloc() é utilizado,


basicamente,​ ​para​ ​os​ ​seguintes​ ​fins​ ​em​ ​um​ ​código​ ​CUDA:
​ evice​.
1. O​ ​ponteiro​ ​pode​ ​ser​ ​passado​ ​para​ ​outras​ ​funções​ ​que​ ​executam​ ​no​ d
2. O ponteiro pode ser utilizado para ler ou escrever na memória da GPU a partir de
código​ ​que​ ​executa​ ​no​ ​device​.
3. Entretanto, o ponteiro não pode ser usado para ler ou escrever na memória da GPU
a​ ​partir​ ​de​ ​código​ ​executado​ ​no​ ​host.

4.1.4.​ ​Liberando​ ​espaço​ ​com​ ​cudaFree()

Se você observou o código com atenção, percebeu que, da mesma forma que é
utilizado ​free() para liberar espaço alocado em memória com ​malloc() no padrão C,
também​ ​existe​ ​o​ ​cudaFree()​ ​para​ ​liberar​ ​espaço​ ​alocado​ ​da​ ​memória​ ​pelo​ c
​ udaMalloc()​.

4.1.5.​ ​Acessando​ ​dados​ ​da​ ​memória​ ​do​ ​dispositivo​ ​com​ c


​ udaMemcpy()

Até aqui aprendemos que é possível alocar e liberar espaço de memória no ​device
(GPU), porém vimos que não é possível alterar este endereço a partir de código no ​host​.
Devido a isso, a seguir veremos duas maneiras mais comuns de acessar a memória do
device​: utilizando ponteiros dentro do código do ​device e realizando chamadas
cudaMemcpy()​.
O primeiro método de ponteiros dentro do código do ​device funciona da mesma
forma que o padrão em C utilizado no host​. Utilizando um ponteiro dentro do ​device​, o
resultado é armazenado na memória que é apontada. Vamos tomar como exemplo a
seguinte expressão executada no ​device​: ​*c = a + b​. São somados os parâmetros ​‘a’ e ​‘b’ e
o resultado é armazenado na memória apontada por ​‘c’​. Para isso, é necessário passar um
ponteiro​ ​por​ ​parâmetro,​ ​como​ ​no​ ​código​ ​utilizado​ ​na​ ​Figura​ ​7.
Além disso, podemos acessar a memória utilizando a função ​cudaMemcpy() a partir
do código ​host​. Esta função funciona exatamente como ​memcpy() em C padrão. O primeiro
parâmetro é a variável a receber a cópia (destino), o segundo é a variável de origem, o
terceiro é o tamanho que será copiado e o último, diferente do C padrão, é uma instrução
informando a origem dos ponteiros, se do ​host ou ​device​. No exemplo abaixo,
cudaMemcpyDeviceToHost informa que o ponteiro de origem pertence ao ​device e o que
receberá a cópia será do ​host. O oposto seria ​cudaMemcpyHostToDevice, ​onde a fonte é
no​ ​host​ ​e​ ​o​ ​destino​ ​é​ ​no​ ​device​.

5.​ ​Exemplo​ ​de​ ​Paralelização​ ​de​ ​Operações​ ​em​ ​Vetor

Neste capítulo será demonstrado e explicado um algoritmo que atribui a um


vetor o valor de seu índice elevado ao quadrado utilizando processamento em GPU com
CUDA. Imagine que tenhamos uma lista muito grande de números e desejamos exibir o
valor de cada índice do vetor elevado ao quadrado. Isso será feito utilizando vetores de
forma​ ​paralela.​ ​A​ ​Figura​ ​8​ ​ilustra​ ​nosso​ ​objetivo.

Figura​ ​8.​ ​Vetor​ ​contém​ ​seu​ ​índice​ ​elevado​ ​ao​ ​quadrado.​ ​[4]

Uma solução tradicional com implementação sequencial, resolveria o problema


utilizando um loop de repetição (for, while, etc.) iterando em cada posição do vetor e
realizando uma multiplicação. Desta maneira, a CPU iria realizar todo o processamento
sequencialmente (uma iteração do loop de cada vez após a outra). Utilizando CUDA, podem
ser utilizados os núcleos da GPU para o processamento das iterações do loop de forma
totalmente paralela, ou seja, ao mesmo tempo. Cada iteração do loop será executada
separadamente em cada ​core (núcleo) de forma paralela. A Figura 9 ilustra a divisão em
mais CPUs do processamento referido em uma função que será executada nos núcleos da
GPU. A variável ​“tid” representa o índice do loop, que é a posição do vetor que será
somada. Cada bloco possui seu ​tid para poder processar o loop completo separadamente.
Além​ ​disso,​ ​a​ ​variável​ ​N​ ​é​ ​uma​ ​constante​ ​que​ ​define​ ​o​ ​tamanho​ ​dos​ ​vetores.
Figura​ ​9.​ ​Execução​ ​do​ ​mesmo​ ​código​ ​em​ ​CPUs​ ​diferentes​ ​com​ ​valores​ ​diferentes.

5.1.​ ​A​ ​Função​ ​main()​.

Na​ ​imagem​ ​a​ ​seguir​ ​será​ ​demonstrado​ ​o​ ​código​ ​em​ C


​ ​ ​utilizando​ ​CUDA​​ ​para​ ​realizar
o​ ​processamento.​ ​Mas,​ ​por​ ​enquanto,​ ​vamos​ ​observar​ ​apenas​ ​a​ ​função​ m ​ ain()​.​ ​Este​ ​código
não​ ​possui​ ​nada​ ​que​ ​não​ ​tenhamos​ ​estudado​ ​ainda.

Podem ser observados alguns padrões utilizados tanto no código da Figura 10 como
nos​ ​exemplos​ ​dos​ ​capítulos​ ​anteriores:

● Alocamos o array no ​device utilizando ​cudaMalloc() (array: dev_vet) para


armazenar​ ​o​ ​resultado.

● ​ udaFree()​ ​para​ ​limpeza.


Como​ ​programador​ ​consciente,​ ​sempre​ ​é​ ​utilizado​ c

● Utilizando ​cudaMemcpy()​, os dados de entrada (vetores) são copiados para o


device utilizando o parâmetro ​cudaMemcpyHostToDevice​. O resultado no ​device é
copiado​ ​de​ ​volta​ ​para​ ​o​ ​host​ ​utilizando​ ​cudaMemcpyDeviceToHost​.

● O código de ​device é executado na função ​multi() a partir da ​main() do ​host


utilizando​ ​a​ ​sintaxe​ ​de​ ​multi<<<N,1>>>.​

Figura​ ​10.​ ​Função​ ​main()​ ​vetor​ ​ao​ ​quadrado​ ​em​ ​CUDA.


No capítulo anterior, a explicação da chamada da função de ​kernel e os números
dentro dos três sinais de maior e menor foi muito sucinta. Nos exemplos do capítulo anterior
era utilizado somente ​<<<1,1>>> como parâmetros, no entanto, neste exemplo foi usado
um​ ​número​ ​diferente​ ​de​ ​1​ ​da​ ​seguinte​ ​forma:​ ​<<<N,1>>>​.​ ​O​ ​que​ ​isso​ ​significa?
O primeiro número desse parâmetro representa o número de blocos paralelos nos
quais é desejado que execute a função ​kernel​. Por exemplo, se for passado ​<<<2,1>>>​,
serão criadas 2 cópias do ​kernel e executadas em blocos paralelos. Isso facilita a
programação paralela, pois apenas indicando ​<<<256,1>>>​, já é possível obter 256 blocos
executando em paralelo. No caso de ​<<<N,1>>>​, N representa o tamanho do vetor, ou seja,
todas​ ​as​ ​posições​ ​do​ ​vetor​ ​serão​ ​computadas​ ​em​ ​paralelo.

5.2.​ ​A​ ​função​ ​de​ ​kernel​ ​multi().

A Figura 11 demonstra a implementação da função de ​kernel​, executada na GPU,


chamada de ​multi() para multiplicação dos números e geração do vetor resultante. Observe
​ ain()​.
que​ ​os​ ​parâmetros​ ​passados​ ​são​ ​os​ ​mesmo​ ​da​ ​chamada​ ​da​ ​função​ ​na​ m

Figura​ ​11.​ ​Função​ ​de​ ​kernel​ ​nomeada​ ​“add”.

À primeira vista, a variável ​blockIdx.x parece causar erro de sintaxe por ser utilizada
como valor para ​tid​, porém não ter sido declarada ou definida. No entanto, não é necessário
definir a variável ​blockIdx​. Esta é uma das variáveis incorporadas que CUDA define para
nós. É uma variável muito importante, sendo utilizada para definir o ​tid​, pois contém o valor
do índice do bloco para qualquer bloco que estiver executando o código do ​device​.
Conforme dito anteriormente, definimos o número de blocos em paralelo no seguinte
parâmetro ​<<<N,1>>>​. A variável ​blockIdx.x identifica o índice de cada um dos blocos,
representando cada iteração do loop sequencial que era necessário para percorrer o vetor.
Por isso, não utilizamos um loop (for, while, etc) em qualquer lugar do código, tanto no ​host
como ​device​. O número de iterações é definido pelo número de blocos paralelos. A Figura
12 ilustra os blocos com cópias da função ​kernel com valores da variável ​tid diferentes
executados​ ​em​ ​paralelo.
Figura​ ​12.​ ​Chamada​ ​de​ ​kernel​ ​em​ ​diferentes​ ​blocos.

Dessa forma, a computação paralela se torna bastante simples. No exemplo,


utilizamos um vetor apenas com 10 posições, porém podem ser usados vetores de 1.000,
10.000 ou 100.000 posições, incluindo matrizes e problemas mais complexos e com
necessidade​ ​de​ ​grande​ ​processamento​ ​de​ ​dados.

6.​ ​Conclusão

Conforme o conteúdo apresentado, CUDA é uma tecnologia que permite


programação paralela utilizando os diversos núcleos presentes em uma placa de vídeo.
Pode ser considerada uma linguagem que proporciona grande poder computacional e, ao
mesmo tempo, esconde muitas das complexidades que seriam encontradas como na
transferência de dados entre memórias ou na distribuição e mapeamento dos blocos
paralelos entre os núcleos da GPU. Sendo assim, podemos desenvolver um código de
forma que utilize programação concorrente sem muita complexidade de código, resultando
em um alto desempenho comparado a outros programas quando executados de forma
sequencial. Podemos usufruir desse desempenho para otimização em tempo de resposta
para​ ​algoritmos​ ​e​ ​soluções​ ​de​ ​software​ ​desenvolvidas.
7.​ ​Referências

[1]​ ​MACHADO,​ ​J.​ ​“O​ ​que​ ​é​ ​GPU?”


Disponível​ ​em:​ ​https://www.tecmundo.com.br/hardware/1127-o-que-e-gpu-.htm
Acessado​ ​em​ ​Novembro/2017

[2]​ ​NVIDIA,​ ​“O​ ​QUE​ ​É​ ​COMPUTAÇÃO​ ​ACELERADA​ ​POR​ ​DE​ ​PLACAS​ ​DE​ ​VÍDEO?”
Disponível​ ​em:​ ​http://www.nvidia.com.br/object/what-is-gpu-computing-br.html
Acessado​ ​em​ ​Novembro/2017

​ awrence​ ​Livermore​ ​National


[3]​ ​Barney,​ ​B.​ ​(2010).​ ​“Introduction​ ​to​ ​parallel​ ​computing.”​ L
Laboratory​,​ ​6(13):10

[4]​ ​SANDERS,​ ​J.,​ ​KANDROT,​ ​E.,​ ​“Cuda​ ​by​ ​example​ ​-​ ​An​ ​Introduction​ ​to​ ​General-Purpose
GPU​ ​Programming”.

[5]​ ​MUHAMMAD,​ ​A.,​ ​MOHAMED,​ ​G.,“CUDA​ ​and​ ​Caffe​ ​for​ ​deep​ ​learning”
Disponível​ ​em:​ ​https://pt.slideshare.net/AmgadMuhammad/cuda-and-caffe-for-deep-learning
Acessado​ ​em:​ ​Novembro/2017
COMPUTAÇÃO ESCALÁVEL

Infraestrutura para Computação


Paralela e Distribuída
ROTEIRO

• A importância da infraestrutura

• Componentes

• Infraestrutura Exemplo

• Open Compute Project


A IMPORTÂNCIA DA INFRAESTRUTURA

POR QUE SE PREOCUPAR COM A INFRAESTRUTURA?

• É muito comum os usuários da rede ou de aplicações que


“rodam” na nuvem se queixarem de lentidão, de queda do
link de comunicação, de falhas de segurança, etc
• O que está mais próximo do usuário é resultado da sua
manipulação com ferramentas, programas, conectividade
• É muito complexo para um usuário ter que saber que a
lentidão na sua conexão pode ser, por exemplo:
 devido a rompimento de uma cabo de fibra ótica
 de discos de armazenamentos queimados
 de servidores de DNS offline, etc.
A IMPORTÂNCIA DA INFRAESTRUTURA

No contexto atual, em que grande parte das aplicações


executam em algum tipo de nuvem computacional,
muitos pontos precisam ser considerados:

• Como garantir a conectividade até o data center?


• Como garantir a operacionalização dos servidores
disponíveis para os usuários?
• E a segurança de acesso?
• E se eu quiser escalar a minha aplicação para atender
uma demanda de acesso que tende a crescer
exponencialmente?
A IMPORTÂNCIA DA INFRAESTRUTURA

Continua...
Outras questões não menos importantes também se
destacam:

• Custo energético para manter um data center


• Autonomia pós-desastre da estrutura ou de
componentes da mesma
• Disco, placa mãe, processadores com problemas
• Conectividade limitada (por conta de falha em
dispositivos como switch, roteadores)
COMPONENTES

GRANULARIDADE GROSSA

Servidores (banco de dados, firewalls, storage,


autenticação, réplicas), switches, roteadores,
nobreaks e bancos de baterias, rack, ventilação
(sistema de refrigeração com ar-condicionados),
sistemas de alarme do ambiente, controle de acesso
ao local onde ficam armazenados os servidores no
data center, barramento de energia elétrica, geradores,
etc.
COMPONENTES

GRANULARIDADE FINA

• Os componentes dos servidores em tipos e


quantidades
• Placas de redes, discos (mecânicos ou SSD), placas
mãe com 1 ou N processadores, placas gráficas para
processamento de alto desempenho (CUDA ou
OpenCL), fontes (em geral reduntantes) → caso uma
apresente problema a outra mantem o hardware
ligado
COMPONENTES

Já imagino um um Data Center dentro de um A350?

Assista a este vídeo curto para ter a ideia de uma


pequena estrutura distribuída que ajuda no controle
da aeronave

https://www.aeroin.net/piloto-airbus-a350-
mostra-compartimento-secreto/
INFRAESTRUTURA EXEMPLO

Laboratório de Sistemas Distribuídos e Programação


Concorrente

 lasdpc.icmc.usp.br

4 clusters independentes que formam uma nuvem


privada (andromeda, halley, cosmos, taurus)

 Total de 60 servidores
 Intel e AMD
 http://infra.lasdpc.icmc.usp.br/
INFRAESTRUTURA EXEMPLO

Esta infraestrutura é atualmente desenvolvida sob as


seguintes distribuições:

 Ubuntu 22.04 LTS


 Freenas (Storages)
 ClearOS (Firewall e Autenticação)
 Virutalizadores como KVM/Qemu e HyperV (Microsoft)
INFRAESTRUTURA EXEMPLO

• Estrutura de virtualização baseada no KVM


(Kernel Virtual Machine)

• 318 máquinas virtuais

• Utilizamos somente ferramentas de código fonte


aberto para gerenciar as VMS

 Open Nebula, Open Stack


OPEN COMPUTER PROJECT

• O Open Compute Project (OCP) é uma comunidade


global de líderes em tecnologia que trabalha em
conjunto para liberar infraestruturas de TI
proprietárias para tornar o hardware mais eficiente,
flexível e escalável, facilitando a personalização

• Redução de Custos

 https://www.opencompute.org/
OPEN COMPUTE PROJECT

O PROJETO EM LINHAS GERAIS PROMOVE:

• Um ecossistema dinâmico do setor para a


implantação global de datacenters na nuvem
• Compartilhamento do mesmo servidor e os mesmos
projetos de datacenter que capacitam a nuvem em
hiperescala
• Organizações de todos os portes podem melhorar o
desempenho, a eficiência, o consumo de energia e
os custos de seus datacenters.
OPEN COMPUTE PROJECT

NO PROJETO DE HARDWARE PARA NUVEM EM GRANDE ESCALA:

• Todas as especificações de projeto em software livre


• Os operadores de datacenters e de TI aproveitam a
inovação desenvolvida pela comunidade para escalar
os projetos de hardware
OPEN COMPUTE PROJECT
BIBLIOGRAFIA

1. https://www.opencompute.org/

2. https://en.wikipedia.org/wiki/Open_Compute_Project

3. https://www.se.com/br/pt/work/solutions/for-business/data-centers-and-networks/open-compute/

4. https://azure.microsoft.com/pt-br/global-infrastructure/hardware-innovation/

5. https://azure.microsoft.com/pt-br/blog/microsofts-project-olympus-delivers-cloud-hardware-innovation-at-scale/

6. https://www.opencompute.org/wiki/Server/ProjectOlympus

7. https://www.aeroin.net/piloto-airbus-a350-mostra-compartimento-secreto/
COMPUTAÇÃO ESCALÁVEL

Clusters
ROTEIRO

• Introdução

• Componentes de cluster

• Categorias de cluster

• Como funciona

• Conclusões
INTRODUÇÃO

• Cluster significa uma combinação de dispositivos


computacionais interligados por uma rede de
comunicação que envolve software e hardware

• São utilizados para permitir alta disponibilidade, o que


tende a melhorar a confiabilidade da solução

• Permitem muito mais computação do que um


computador isolado
COMPONENTES DE CLUSTER

Os blocos básicos de qualquer cluster devem envolver:

• Hosts (Nós de processamento)

• Rede de comunicação

• Arquitetura da rede de comunicação


CATEGORIAS DE CLUSTER

ALTA DISPOBILIDADE

• Aquele que tende a ser


resistente a falhas de
hardware, software e
energia

• O objetivo é manter os
serviços em operação o
maior tempo possível
CATEGORIAS DE CLUSTER

BALANCEAMENTO DE CARGA
• Técnica utilizada para distribuir carga de trabalho de
maneira uniforme entre dois ou mais hosts, enlaces de
comunicação, discos de armazenamento e outros recursos
computacionais com o objetivo de:
 Maximizar o desempenho
 Minimizar o tempo de resposta
 Evitar a sobrecarga

• O balanceamento de carga aumenta a confiabilidade por


meio da redundância dos recursos computacionais
disponíveis
CATEGORIAS DE CLUSTER

BALANCEAMENTO DE CARGA
CATEGORIAS DE CLUSTER

ALTO DESEMPENHO

• Utilizados para aplicações que exigem muito


processamento computacional

• Sistemas utilizados em pesquisas científicas, por


exemplo, podem se beneficiar deste tipo de cluster
por necessitarem analisar uma grande variedade de
dados rapidamente e realizar cálculos bastante
complexos
CATEGORIAS DE CLUSTER

ALTO DESEMPENHO
COMO FUNCIONA

• Usuário submete um job para o nó mestre do cluster


• Job
 Uma aplicação que vai executar no cluster
• Um escalonador de jobs no nó mestre associa cada
tarefa definida no job para núcleos ou nós de
processamento do cluster
• Os resultados de processamento de cada tarefa são
retornados para o usuário por meio do nó mestre
COMPONENTES

BENEFÍCIOS TIPOS DE APLICAÇÕES

• Disponibilidade • Orientada a
processamento
• Desempenho intensivo (CPU)
• Escalabilidade • Orientada a entrada e
saída (I/O)
• Transacionais
COMPONENTES

LIMITAÇÕES

• Latência tende a ser alta se não for utilizada tecnologia


de comunicação com alta largura de banda
(localmente)

• O software para rodar no cluster tende a ser mais


complexo do que aquele que vai executar em um único
nó (host)
BIBLIOGRAFIA

1. https://pt.wikipedia.org/wiki/Balanceamento_de_carga
2. https://www.unirios.edu.br/revistarios/media/revistas/2020/27/cluster_e_balanceamento_de_carga.pdf
3. http://www.din.uem.br/~mestrado/diss/2006/gorino.pdf
4. https://docs.microsoft.com/pt-br/data-integration/gateway/service-gateway-high-availability-clusters
5. https://www.devmedia.com.br/configurando-um-cluster-de-tomcat-com-balanceamento-de-carga/22631
6. https://www.researchgate.net/publication/228555383_MONITORAMENTO_DISTRIBUIDO_DE_CLUSTERS_E
_GRIDS_COMPUTACIONAIS_UTILIZANDO_O_GANGLIA
7. https://bugbusters.com.br/2018/05/22/servidor-em-cluster/
8. https://www.canalti.com.br/computacao/cluster-o-que-e-historia-tipos-de-cluster-exemplo/
COMPUTAÇÃO ESCALÁVEL

Grids
ROTEIRO

• O que é um Grid?

• Características

• Infraestrutura

• Exemplos

• Internet x WWW x Grid x Cloud


O QUE É UM GRID?

• Trata-se de uma coleção de recursos computacionais


e de comunicação utilizados para execução de
aplicações

• Um usuário vê o grid como uma entidade única

ORIGEM IAN FOSTER (1998)


Power Grid, termo que Foi o primeiro a
determina o sistema de geração abordar o termo Grid
e distribuição de energia Computacional
CARACTERÍSTICAS

Grids são formados por recursos heterogêneos, o que


engloba clusters, supercomputadores, desktops e até
dispositivos móveis

Elementos de um Grid:

• Nó mestre (eventualmente replicado)


• Nós de execução
• Nós de submissão
• Interligação
• Rede de comunicação pública de larga escala:
Internet!
CARACTERÍSTICAS

PERVASIVIDADE
• O grid está disponível em todo lugar
• Plugue e use (assim como a rede elétrica)

VISÃO UNIFORME DOS RECURSOS COMPUTACIONAIS


• O usuário executa uma aplicação no grid, sem saber
quais serão os nós envolvidos

ARMAZENAMENTO REMOTO DE DADOS


• Dados do usuário podem ser armazenados de modo
transparente e confiável no grid
INFRAESTRUTURA
INFRAESTRUTURA

MIDDLEWARE PARA GERENCIAMENTO DO GRID


• Gerencia todo o funcionamento do grid, desde a
descoberta, alocação e reserva de recursos, até o
controle de acesso, a detecção de falhas, a
manutenção de registros de utilização, etc.

FUNDAMENTADO EM TECNOLOGIAS JÁ EXISTENTES E


DISPONÍVEIS
• Comunicação: protocolos da Internet / Web
• Software: tecnologia de Web Services
INFRAESTRUTURA

Globus Toolkit
• http://www.globus.org
• Gratuito e de código aberto
• Baseado nos seguintes padrões e tecnologias:
• Open Grid Services Architecture (OGSA)
• Web Services (SOAP, WSDL, Web Service
Resource Framework, WS-Management)
• Job Submission Description Language (JSDL)
• Distributed Resource Management
• Application API (DRMAA)
• Grid Security Infrastructure (GSI)
EXEMPLOS DE USO

Large Hadron Collider (LHC) Computing Grid:


https://wlcg.web.cern.ch/

World Community Grid


https://www.worldcommunitygrid.org/
INTERNET X WWW X GRID X CLOUD

Internet WWW
• Infraestrutura de • Aplicação distribuída
rede que conecta para o compartilhamento
milhões de de informações/
computadores documentos construídos
(baseada na pilha sob a Internet
TCP/IP) • Início na década de 1990
• Criada na década
de 1970
INTERNET X WWW X GRID X CLOUD

GRID
• Serviço também construído sob a Internet
• No Grid, computadores compartilham poder
computacional e recursos como armazenamento de
disco, aplicações e bases de dados

CLOUD
• Modelo que permite o acesso de forma onipresente,
conveniente e sob demanda a um conjunto de
recursos computacionais compartilhados e
configuráveis (por exemplo redes, servidores,
armazenamento, aplicações e serviços)
BIBLIOGRAFIA

1. https://netlib.org/utk/people/JackDongarra/SLIDES/japan-199/sld001.htm

2. https://www.globus.org/

3. https://www.unicore.eu/

4. https://www.informit.com/articles/article.aspx?p=169508&seqNum=5

5. https://wlcg.web.cern.ch/

6. http://www.univasf.edu.br/~andreza.leite/aulas/SO/GridCluster.pdf

7. https://www.worldcommunitygrid.org/

8. https://csrc.nist.gov/publications/detail/sp/800-145/final
COMPUTAÇÃO ESCALÁVEL

Cloud
ROTEIRO

• O que é uma Cloud?

• Características

• Infraestrutura

• Exemplos
O QUE É UMA CLOUD?
• Tecnologia que permite acesso remoto a recursos
computacionais, seja hardware ou software sob
demanda, e que utiliza massivamente tecnologias de
virtualização

• Termo utilizado para descrever uma rede global de


servidores, tendo cada um deles uma função única

• Tais servidores foram desenvolvidos para armazenar


e gerir dados, executar aplicações ou fornecer
conteúdos ou um serviço, como transmissão em
fluxo de vídeos, webmail, software de produtividade
para escritórios ou redes sociais
CARACTERÍSTICAS

SERVIÇO SOB DEMANDA


• Usuário solicita os recursos que deseja
• Obtenção simplificada de recursos, sem interação
humana

POOL DE RECURSOS
• Recursos são compartilhados entre diversos usuários
e alocados com base na demanda

ACESSO VIA REDE DE COMUNICAÇÃO


• Recursos podem ser acessados remotamente usando
diversos tipos de dispositivo
CARACTERÍSTICAS

ELASTICIDADE
• Recursos alocados aos usuários podem variar em
função da demanda

MEDIÇÃO
• Provedor monitora o uso dos recursos para controlar
e tarifar
MODELOS

SERVIÇO

SAAS PAAS

Também conhecido como Fornece aos


software baseado em desenvolvedores de
cloud, ou aplicativos em software uma plataforma
cloud, é um software de sob demanda (hardware,
aplicativo hospedado em solução completa de
cloud, que é acessado e software, infraestrutura e
usado por meio de um até ferramentas de
navegador da web desenvolvimento)
MODELOS

SERVIÇO

IAAS

Acesso sob demanda a recursos fundamentais de


computação (servidores físicos e virtuais, rede e
armazenamento) por meio da internet com forma de
pagamento conforme a utilização
MODELOS

SERVIÇO
MODELOS

IMPLANTAÇÃO

PÚBLICA PRIVADA

Formada por recursos Organização mantém a


computacionais infraestrutura sob o seu domínio
(servidores e oferecendo acesso restrito aos
armazenamento) usuários. É utilizada por
fornecidos por organizações que devem seguir
terceiros e disponíveis regras específicas sobre
para qualquer usuário segurança e privacidade de dados
ou organização que (instituições financeiras e
deseje utilizá-los governamentais)
MODELOS

IMPLANTAÇÃO

HÍBRIDA

• União de Cloud Pública e Cloud Privada


• Compartilha dados e aplicações entre ambos os tipos
de nuvens
• Com alguns recursos disponibilizados de forma
privada e outros disponibilizados publicamente
MODELOS

IMPLANTAÇÃO
INFRAESTRUTURA

TODA BASEADA EM GRANDES DATACENTERS


• Espalhados geograficamente pelo mundo
• Utiliza virtualização dos recursos computacionais
INFRAESTRUTURA

Azure
BIBLIOGRAFIA

1. https://www.google.com/intl/pt-BR/about/datacenters/gallery/
2. https://azure.microsoft.com/pt-pt/resources/cloud-computing-dictionary/what-is-the-cloud/
3. https://www.ibm.com/br-pt/cloud/learn/cloud-computing
4. http://jornadaparanuvem.com.br/fundamentos-de-cloud-computing/os-tres-modelos-de-servico/
5. https://tiinside.com.br/03/09/2017/hitachi-lanca-plataforma-unificada-que-simplifica-implementacao-da-
nuvem-hibrida/
6. https://forum.ibgp.net.br/guia-pratico-para-nuvem-computacional-baseado-em-padroes-cscc/
7. https://www.dinamio.com.br/blog/2019/10/25/cloud-computing-conceitos-e-caracteristicas-de-iaas-paas-e-
saas/
COMPUTAÇÃO ESCALÁVEL

Frameworks para Computação


Paralela - OpenMP
ROTEIRO

• O que é OpenMP
• Modelo de Programação
• Modelo de Execução
• Variáveis
• Exemplo
O QUE É OPENMP?

 É um modelo de programação de memória


compartilhada que nasceu da cooperação entre um
grupo de grandes fabricantes de software e hardware

 API para programação paralela de arquiteturas


multiprocessor foi definida inicialmente para ser
usada em programas C / C++ (1998) e Fortran (1997)
tanto Linux quanto Windows

 Não é uma implementação, e sim uma especificaçãoX


O QUE É OPENMP?

Objetivos
 Ser o padrão de programação para arquiteturas de memória
compartilhada
 Estabelecer um conjunto simples e limitado de diretivas de
programação
 Possibilitar a paralelização incremental de programas
sequenciais
 Permitir implementações eficientes em problemas de
granularidade fina, média e grossa
O QUE É OPENMP?
Componentes
 Bibliotecas de funções
 Diretivas de compilação
 Variáveis de ambiente

Limitações
 Quanto mais variáveis compartilhadas entre as
threads, mais difícil deve ser o trabalho para garantir
que a visão das variáveis são atuais – coerência de
cache
 Outras limitações são baseadas em hardware e estão
associadas à forma como muitos SMPs são
fisicamente capazes de compartilhar o mesmo
espaço de memória
O QUE É OPENMP?

 O aspecto mais difícil de criar um programa de memória


compartilhada é traduzir o que se deseja para uma versão
multi-thread
 Outro ponto é fazer a versão muilti-thread do programa
operar corretamente

 Sem problemas com variáveis compartilhadas


 Situações de condições de corrida/disputa
 Detecção e Depuração dessas condições
 Questões relativas ao tempo de execução
MODELO DE PROGRAMAÇÃO

Paralelismo Explícito
 Cabe ao programador anotar as tarefas para execução
em paralelo e definir os pontos de sincronização. A
anotação é feita por utilização de diretivas de
compilação embarcadas no código do programa
MODELO DE PROGRAMAÇÃO

Multithread Implícito
 Neste caso um processo é visto em conjunto de
threads que se comunicam por meio da utilização de
variáveis compartilhadas
 Criação

 Início

 Término

 Feito de forma implícita pelo ambiente de execução


sem que o programador tenha que se preocupar com
tais detalhes
MODELO DE PROGRAMAÇÃO

Multithread Implícito
 Espaço de endereçamento global compartilhado entre
as threads
 Variáveis podem ser compartilhadas ou privadas para
cada thread
 Controle, manuseio e sincronização das variáveis
envolvidas nas tarefas paralelas são transparentes ao
programador
MODELO DE EXECUÇÃO
Fork-Join
 Todos os programas iniciam sua execução com um processo
mestre
 O master thread executa sequencialmente até encontrar um
construtor paralelo, momento em que cria um team de threads
 O código delimitado pelo construtor paralelo é executado em
paralelo pelo master thread e pelo team de threads
 Quando completa a execução paralela, o team de
threads sincroniza em uma barreira implícita com o
master thread
 O team de threads termina a sua execução e o
master thread continua a execução sequencialmente
até encontrar um novo construtor paralelo
 A sincronização é utilizada para evitar a competição
entre as threads
MODELO DE EXECUÇÃO
Estrutura Básica de um Programa OpenMP
MODELO DE EXECUÇÃO

 Definições da biblioteca em omp.h


 Implementação em libgomp.so

 Compilação de um programa OpemMP

 É preciso utilizar a opção

 -fopenmp
VARIÁVEIS

 Declarar acesso entre as threads


 Private

 Pertencem e são conhecidas apenas a cada

segmento específico

int id, nthreads;


pragma omp parallel private(id)
{id = omp_get_thread_num();
VARIÁVEIS
 Declarar acesso entre as threads
 Shared

 Variáveis compartilhadas são conhecidas por todas as

threads
 Cuidados devem ser tomados quando utilizadas essas

variáveis, já que a manipulação incorreta poderá dificultar


a detecção de erros como condições de disputa e
deadlocks

int id, nthreads, A, B; A = getA();


B = getB();
#pragma omp parallel private(id,nthreads) shared(A,B)
{ id = omp_get_thread_num();
VARIÁVEIS

 Inicialização de Variáveis
 Firstprivate
 Permite inicializar uma variável privada na thread
master antes de entrar em uma região paralela do
código. Caso contrátrio, todas as variáveis privadas
serão consideradas não inicializadas no início da
thread

int id, myPi; myPi = 3.1459


#pragma omp parallel private(id) firstprivate(myPi)
{ id = omp_get_thread_num();
MAPEAMENTO PARA THREADS
EXEMPLO
Hello World!
BIBLIOGRAFIA

1.http://www.openmp.org
2.Introduction to Parallel Computing, Ananth Grama, Anshul
Gupta, George Karypis, Vipin Kumar - 2ª ed., Addison Wesley
3.OpenMP - https://hpc-tutorials.llnl.gov/openmp/
COMPUTAÇÃO ESCALÁVEL

Frameworks para Computação


Paralela - OpenMPI
ROTEIRO

• O que é o OpenMPI?
• Motivação
• Características
• Conceitos Básicos
• Principais Funções
O QUE É OPENMPI?

MPI (Message Passing Interface)

O modelo de passagem de mensagens é um conjunto


de processos que possuem acesso à memória local.
As informações são enviadas da memória local do
processo para a memória local do processo remoto
O QUE É OPENMPI?

MPI é uma biblioteca de Message Passing


desenvolvida para ambientes de memória distribuída,
máquinas massivamente paralelas, NOWs (network of
workstations) e redes heterogêneas
Padrão criado por um consórcio entre empresas e
universidades
É uma biblioteca de rotina que fornece funcionalidade
básica para que os processos se comuniquem.
O paralelismo é explícito (programador é responsável
pela distribuição)
MOTIVAÇÃO

 Necessidade de poder computacional


 Dificuldades na melhoria dos processadores

sequenciais
 Custo x Benefício

 Dificuldades

 Comunicação, coordenação, sincronização


 Distribuição de trabalho
CARACTERÍSTICAS
Vantagens do MPI
 Maduro
 Portabilidade é facilidade
 Combina eficientemente com diversos hardwares
 Implementações proprietárias e públicas
 Interface com usuário
 Buffer de manipulação
 Permite abstrações de alto nível
 Desempenho
Desvantagens do MPI
 O ambiente de controle de execução depende da
implementação
 Comunicação entre os hosts pode ser o gargalo da
solução
CARACTERÍSTICAS
Thread Safety
 Comunicação ponto-a-ponto
 Modos de comunicação: standard, synchronous,
ready, buffered
 Buffers estruturados
 Tipos de dados derivados
Comunicação Coletiva
 Nativo já incorporado, operações coletivas definidas pelo
usuário
 Rotinas de movimentação de dados
Perfis
 Usuários podem interceptar chamadas MPI e chamar
suas próprias ferramentas
CONCEITOS BÁSICOS

Processo
 Cada parte do programa quebrado é chamado de
processo. Os processos podem ser executados em
uma única máquina ou em várias

Rank
 Todo o processo tem uma identificação única
atribuída pelo sistema quando o processo é
inicializado. Essa identificação é contínua e
representada por um número inteiro, começando
de zero até N-1, cujo N é o número de processos.
Cada processo tem um rank, e ele é utilizado para
enviar e receber mensagens
CONCEITOS BÁSICOS
Rank
 Usado pelo desenvolvedor para especificar
a fonte e o destino de mensagens
 Pode ser usado condicionalmente pela

aplicação para controlar a execução do


programa
if rank == 0
do ...
else if rank == 1
do …
CONCEITOS BÁSICOS
Grupos
 Grupo é um conjunto ordenado de N processos. Todo
e qualquer grupo é associado a um comunicador muitas
vezes já predefinido como "MPI_COMM_WORLD"
Comunicador
 O comunicador é um objeto local que representa o
domínio (contexto) de uma comunicação (conjunto
de processos que podem ser contatados). O
MPI_COMM_WORLD é o comunicador predefinido
que inclui todos os processos definidos pelo usuário
numa aplicação MPI
 As chamadas de MPI_Send e MPI_Recv
correspondentes devem possuir o mesmo
comunicador
CONCEITOS BÁSICOS

Application Buffer
 É o endereço de memória, gerenciado pela aplicação,
que armazena um dado que o processo necessita enviar
ou receber

System Buffer
 É um endereço de memória reservado pelo sistema
para armazenar mensagens.

Count
 Indica o número de elementos de dados de um tipo,
para ser enviado
CONCEITOS BÁSICOS

Type
 O MPI pré define tipos de dados elementares
Tag
 Inteiro (não negativo). Utilizado para identificar
unicamente uma mensagem. As chamadas de
MPI_Send e MPI_Recv correspondentes devem
possuir a mesmo tag

Status
 Para uma operação de receive, indica a fonte da
mensagem e a tag da mensagem. Em C, um ponteiro
para uma estrutura pré-definida (MPI_STATUS).
Adicionalmente, o número de bytes é obtido do status,
via rotina MPI_Get_Count
PRINCIPAIS FUNÇÕES

 Em geral são utilizadas:


 MPI_Init

 MPI_Finalize

 MPI_Comm_size

 MPI_Comm_rank

 MPI_Get_processor_name
PRINCIPAIS FUNÇÕES
MPI_Init
 Inicializa um processo MPI
 Deve ser a primeira rotina a ser chamada por cada
processo, pois estabelece o ambiente necessário para
executar o MPI
 Sincroniza todos os processos na inicialização de
uma aplicação MPI
 Utilizada para passar argumentos de linha de
comando para todos os processos
MPI_Finalize
 MPI_Finalize é chamada para encerrar o MPI. Ela
deve ser a última função a ser chamada. É usada
para liberar memória. Não existem argumentos
PRINCIPAIS FUNÇÕES
Exemplo com MPI_Init e MPI_Finalize
PRINCIPAIS FUNÇÕES
MPI_Comm_size
 Determina o número de processos no grupo, associado
com o comunicador
 Usado com o comunicador MPI_COMM_WORLD para
determinar o número de processos utilizados pela aplicação
 Obtém o comunicador como seu primeiro argumento,
e o endereço de uma variável inteira é usada para
retornar o número de processos
MPI_Comm_rank
 Identifica um processo MPI dentro de um determinado
grupo comunicador. Retorna sempre um valor inteiro
entre 0 e n-1, cujo n é o número de processos
PRINCIPAIS FUNÇÕES
Exemplo com MPI_Comm_size e MPI_Comm_rank
PRINCIPAIS FUNÇÕES

MPI_Get_processor_name
 Retorna o nome do nó, cujo processo individual está
executando
 Usa um argumento para guardar o nome da máquina
e outro para o tamanho do nome
PRINCIPAIS FUNÇÕES
Exemplo com MPI_Get_processor_name
BIBLIOGRAFIA

1.https://hpc-tutorials.llnl.gov/mpi/
2.Introduction to Parallel Computing, Ananth Grama, Anshul
Gupta, George Karypis, Vipin Kumar - 2ª ed., Addison Wesley
3.Programação Paralela e Distribuída -
https://www.dcc.fc.up.pt/~ricroc/aulas/1011/ppd/apontamentos
/mpi.pdf
COMPUTAÇÃO ESCALÁVEL

Frameworks para Computação


Paralela - CUDA
ROTEIRO

• Introdução ao CUDA
• Estrutura do CUDA
• Organização das Threads
• Modelo de Memória
• CUDA em Docker e Cloud
• Utilização do CUDA
INTRODUÇÃO AO CUDA

 CUDA é uma plataforma de software e hardware


para computação paralela de alto desempenho
que utiliza o poder de processamento dos
núcleos das GPUs da NVIDIA

 Possui demanda nos campos matemático,


científico e biomédico, além das demandas na
computação e na engenharia devido às
características das aplicações nesses campos,
que são altamente paralelizáveis
INTRODUÇÃO AO CUDA
 O motivo para as GPUS serem tão eficientes é que elas são
exclusivamente dedicadas a processar dados não tendo que
guardar informações de cache ou controlar fluxos de dados
ESTRUTURA DO CUDA
ORGANIZAÇÃO DAS THREADS DO CUDA

 O escalonamento das threads da plataforma


CUDA utiliza dois conceitos: bloco e grid. Através
deles se organiza a repartição dos dados entre as
threads, a organização e a distribuição dos dados
ao hardware

 Em geral, cada bloco dispõe de duas ou três


coordenadas dimensionais dadas por palavras
chave: blockIdx.x, blockIdx.y e blockIdx.z
ORGANIZAÇÃO DAS THREADS DO CUDA

SANDERS, J.; KANDROT, E. CUDA by


example : an introduction to general-
purpose GPU programming. [S.l.]: Addison-
Wesley, 2010. p. 311
ORGANIZAÇÃO DAS THREADS DO CUDA
MODELO DE MEMÓRIA CUDA

 Memória global e memória constante podem ser


escritas e lidas pelo host chamando funções da
API

 Memória global: maior e também a mais lenta


 Memória constante: é pequena e mais rápida

Suporta, basicamente, apenas só leitura


MODELO DE MEMÓRIA CUDA
CUDA EM DOCKER E CLOUD
CUDA EM DOCKER E CLOUD
UTILIZAÇÃO DO CUDA

 Para utilizar o CUDA é preciso:


 Ter uma placa gráfica da Nvidia

 Ter o driver da Nvidia devidamente configurado

no host
 Ter um toolkit contendo compilador e

ferramentas adicionais
 Para saber os requisitos, o site da Nvidia

detalha tais necessidades


 https://developer.nvidia.com/cuda-downloads
APLICAÇÕES

 Ataques cardíacos são a maior causa de mortes no


mundo todo
 Utilização de GPUs com o objetivo de simular o fluxo
sanguíneo e identificar placas arteriais ocultas sem
fazer uso de técnicas de imageamento invasivas ou
cirurgias exploratórias
APLICAÇÕES
 Simulação de moléculas com melhor desempenho
com a utilização de GPUs
 A aceleração do desempenho é resultado da
arquitetura paralela das GPUs
BIBLIOGRAFIA
1.https://docs.nvidia.com/ai-enterprise/deployment-guide/dg-docker.html
2.https://thenewstack.io/nvidia-opens-gpus-for-ai-work-with-containers-
kubernetes/
3.https://medium.com/unicoidtech/usando-nvidia-gpus-no-google-kubernetes-
engine-ee4261713d86
4.https://edisciplinas.usp.br/pluginfile.php/4146828/mod_resource/content/1/M
aterialCUDA.pdf
5.https://www.oficinadanet.com.br/post/14818-o-que-e-cuda
6.https://eradsp2010.files.wordpress.com/2010/10/curso2_cuda_camargo.pdf
7.https://deinfo.uepg.br/~alunoso/2020/SO/Programacao-CUDA/
8.https://lief.if.ufrgs.br/pub/Cursos/Cuda/aula06.pdf
9.http://ubiq.inf.ufpel.edu.br/ippd/lib/exe/fetch.php?media=cuda-lucas_pires_-
_nvidia_cuda.pdf
COMPUTAÇÃO ESCALÁVEL

Frameworks para
Processamento de Dados
em Larga Escala - Spark
ROTEIRO

• Motivação
• O que é Apache Spark?
• Como funciona?
• Ecossistema do Spark
• Benefícios
MOTIVAÇÃO
 Aumento de datasets na Web
 Cliques

 Requisições de servidores

 Dados de localização de dispositivos móveis

 Dados de grafos

 Redes de telefonia

 Redes sociais

 Redes de computadores

 Internet das Coisas

 RFID

 Sensores

 Dados financeiros
MOTIVAÇÃO

 Dados, muitos dados…


 Armazenamento de conteúdo multimídia (Youtube)

 Bolsas de valores

 Dados de usuários de redes sociais

(Instagram, Facebook, etc)


 Grande difusão do armazenamento baseado em
nuvem e dos recursos computacionais
 Para o processamento de grandes datasets

 Já vimos as características de Cloud


 Mais barata

 Escala dinamicamente

 Computação sob demanda


O QUE É O APACHE SPARK?

 É uma alternativa ao Map Reduce para algumas


aplicações
 Um sistema de computação em cluster com baixa
latência
 Usado para grandes conjuntos de dados
 Usado em conjunto com o Hadoop FS
 O MapReduce permite a análise de big data usando
clusters grandes e não confiáveis
 MapReduce carece de primitivas eficientes para
compartilhamento de dados
O QUE É O APACHE SPARK?
 É neste contexto que o Spark entra em cena
 Ao invés de carregar os dados do disco para cada

consulta, por que não fazer o compartilhamento de


dados na memória?
 Acesso à memória é mais rápido se comparado ao

acesso ao disco
 Há APIs para linguagens como:
 Java

 Scala

 Python

 Cache de dados na memória


(para algoritmos iterativos, gráficos e de
aprendizado de máquina, etc.)
O QUE É O APACHE SPARK?
 O Apache Spark suporta análise de dados, aprendizado
de máquina, gráficos, dados de streaming, etc. Ele pode
ler/gravar de uma variedade de tipos de dados e permite
o desenvolvimento em várias linguagens
Scala, Java, Python, R, SQL

DataFrames ML Pipelines
Spark
Spark SQL Streaming
MLlib GraphX
Spark Core

Data Sources
Hadoop HDFS, HBase, Hive, Apache S3, Streaming, JSON, MySQL, and HPC-style
(GlusterFS, Lustre)
COMO FUNCIONA?
Hadoop: Utiliza disco
para compartilhar
HDFS HDFS HDFS dados
Leitura HDFS
Leitura Escrita
Escrita

Iteração 1 Iteração 2

HDFS Spark: Utiliza memória


Leitura para compartilhar
dados

Iteração 1 Iteração 2
COMO FUNCIONA?

 O Spark aborda o problema do acesso compartilhado


aos dados com:
 Conjuntos de dados distribuídos resilientes (RDDs)

 O RDD permite que as aplicações mantenham

conjuntos de trabalho na memória para reutilização


 RDD se destaca como um modelo de programação
 Tolerante a falhas

 Computação distribuída

 Compartilhamento em memória

 Spark é uma implementação do RDD


COMO FUNCIONA?

 Com o RDD
 Somente leitura, coleções particionadas de

objetos
 Um array imutável distribuído

 Criado por meio de transformações paralelas

em dados e armazenamento estável


 Pode ser armazenado em cache para

reutilização eficiente
ECOSSISTEMA DO SPARK
ECOSSISTEMA DO SPARK

Spark Core: é o motor de execução da plataforma Spark.


Ele fornece recursos de computação distribuídos na
memória

Spark SQL: é um mecanismo para o Hadoop Hive


que permite que consultas não modificadas do Hadoop
Hive sejam executadas até 100 vezes mais rápido em
implantações e dados existentes
ECOSSISTEMA DO SPARK

Spark Streaming: é um mecanismo que permite


aplicativos interativos e analíticos poderosos no streaming
de dados

MLLib: é uma biblioteca de aprendizado de máquina


escalável

GraphX: é um mecanismo de computação gráfica


construído em cima do Spark
BENEFÍCIOS

 Generaliza o MapReduce
 Modelo de programação mais rico
 Menos sistemas para dominar
 Melhor gerenciamento de memória
 Menor movimentação de dados que leva a um melhor
desempenho para análises complexas
BIBLIOGRAFIA

1.http://www.prathapkudupublog.com/2018/02/modules-in-
apache-spark.html
2.https://data-flair.training/blogs/apache-spark-ecosystem-
components/
3.https://medium.com/expedia-group-tech/an-introduction-to-
apache-spark-f0795f2d5201
4.https://www.infoq.com/br/articles/apache-spark-introduction/
5.https://docs.microsoft.com/pt-br/azure/databricks/getting-
started/spark/quick-start
COMPUTAÇÃO ESCALÁVEL

Frameworks para Processamento


de Dados em Larga Escala -
Hadoop
ROTEIRO

• Características

• O que é Apache Hadoop?

• Arquitetura do Hadoop

• Ecossistema Hadoop

• Aplicações
CARACTERÍSTICAS

• Linguagem Java

• Modelo de programação Map Reduce

• Arquitetura Mestre/Escravo

• Processamento Distribuído

• Hadoop Distributed Filesystem (HDFS)

• Tolerante a Falhas

• Memória Secundária (Disco)

• Escalável
CARACTERÍSTICAS

• Não é uma linguagem de programação

• Não resolve tudo sobre processamento de


grandes volumes de dados

• Não é processamento em tempo real

• Não é uma lib de aprendizado de máquina


O QUE É APACHE HADOOP?

É uma implementação de código aberto de estruturas


para armazenamento de dados e computação confiável,
escalável e distribuído

É uma arquitetura flexível e altamente disponível para


computação em larga escala e processamento de dados
em uma rede de hardware comum
O QUE É APACHE HADOOP?

Projetado para responder à pergunta: “Como processar


big data com custo e tempo razoáveis?”

Objetivos/Requisitos

• Abstrair e facilitar o armazenamento e o processamento de


conjuntos de dados grandes e/ou em rápido crescimento
• Dados estruturados e não estruturados
• Modelos de programação simples
• Alta escalabilidade e disponibilidade
• Use hardware comum (barato!) com pouca redundância
• Tolerância ao erro
• Mover computação em vez de dados
ARQUITETURA APACHE HADOOP
ARQUITETURA APACHE HADOOP

Distribuída com alguma centralização


• A maior parte do poder computacional e de
armazenamento do sistema está nos nós principais do
cluster
• Os nós principais executam o TaskTracker para aceitar e
responder às tarefas do MapReduce e também o DataNode
para armazenar os blocos necessários o mais próximo
possível
• O nó de controle central executa o NameNode para
acompanhar os diretórios e arquivos do HDFS e o
JobTracker para despachar tarefas de computação para o
TaskTracker
• Escrito em Java, também suporta Python e Ruby
ARQUITETURA APACHE HADOOP

Sistema de Arquivos Distribuídos Hadoop (HDFS)

• Adaptado às necessidades do MapReduce


• Direcionado para muitas leituras de fluxos de
arquivos
• Gravações são mais caras
• Alto grau de replicação de dados (3x por padrão)
• Não há necessidade de RAID em nós normais
• Tamanho de bloco grande (64 MB)
• Reconhecimento de localização de DataNodes na
rede
ARQUITETURA APACHE HADOOP

NameNode
• Armazena metadados para os arquivos, como a
estrutura de diretórios de um FS típico
• O servidor que contém a instância NameNode é
bastante crucial, pois existe apenas um
• Log de transações para exclusões/inclusões de
arquivos, etc. Não usa transações para blocos
inteiros ou fluxos de arquivos, apenas metadados.
• Lida com a criação de mais blocos de réplica quando
necessário após uma falha do DataNode
ARQUITETURA APACHE HADOOP

DataNode

• Armazena os dados reais em HDFS


• Pode ser executado em qualquer sistema de arquivos
subjacente (ext3/4, NTFS, etc.)
• Notifica NameNode de quais blocos ele possui
• NameNode replica blocos 2x no rack local, 1x em
outro lugar
ARQUITETURA APACHE HADOOP

MapReduce Engine

• O JobTracker divide os dados em tarefas menores


(“Mapa”) e os envia para o processo TaskTracker em
cada nó

• O TaskTracker reporta de volta ao nó JobTracker e


relata o progresso do trabalho, envia dados
(“Reduzir”) ou solicita novos trabalhos
ECOSSISTEMA HADOOP
APLICAÇÕES

Publicidade (comportamento do usuário de mineração


para gerar recomendações)

Pesquisas (documentos relacionados ao grupo)

Segurança (busca por padrões incomuns)

Soluções Comerciais
• Dell
• Amazon
• Microsoft
• Cloudera
BIBLIOGRAFIA

1. https://www.ime.usp.br/~ipolato/JAI2012-Hadoop-Slides.pdf

2. http://www.each.usp.br/dc/papers/erad-hadoop-DanielCordeiro.pdf

3. https://www.devmedia.com.br/hadoop-fundamentos-e-instalacao/29466

4. https://johnosd.medium.com/hadoop-seus-componentes-principais-e-sua-evolu%C3%A7%C3%A3o-

cf125c99fadd

5. https://cetax.com.br/apache-hadoop-tudo-o-que-voce-precisa-saber/

6. https://itforum.com.br/noticias/28-bilhoes-de-gigabytes-de-storage-foram-distribuidos-no-primeiro-trimestre/

7. https://www.ime.usp.br/~ipolato/JAI2012-Hadoop-Slides.pdf
COMPUTAÇÃO ESCALÁVEL

Frameworks para Processamento


de Dados em Larga Escala - Kafka
ROTEIRO

• Introdução

• O que é Apache Kafka?

• Arquitetura

• Pontos de Entrada

• Integração de dados e processamento

• Usos do Kafka
INTRODUÇÃO

Há dois tipos de sistema de mensagens:


• Sistema ponto a ponto
• Sistema Publicar-Assinar

Sistema ponto a ponto


• As mensagens são persistidas em uma fila, mas uma mensagem
específica pode ser consumida por no máximo apenas um
consumidor. Depois que um consumidor lê uma mensagem na
fila, ela desaparece dessa fila
INTRODUÇÃO
Sistema Publicar-Assinar
• As mensagens são persistidas em um tópico. Ao contrário do
sistema ponto a ponto, os consumidores podem se inscrever em
um ou mais tópicos e consumir todas as mensagens desse
tópico

• Neste sistema, os produtores de mensagens são chamados de


publicadores e os consumidores de mensagens são chamados
de assinantes
O QUE É APACHE KAFKA?

Kafka é uma plataforma de streaming distribuído

• Alta escalabilidade (partição)


• Tolerante a falhas (replicação)
• Permite alto nível de paralelismo e desacoplamento
entre produtores de dados e consumidores de dados
• Padrão de fato para armazenamento, acesso e
processamento de fluxo de dados quase em tempo
real
• Componente crítico da maior parte da plataforma de
Big Data e, portanto, do ecossistema Hadoop
INTRODUÇÃO
ARQUITETURA
ARQUITETURA
ARQUITETURA

• Um produtor é uma entidade/aplicação que publica


dados em um cluster Kafka, composto por brokers
• Um broker é responsável por receber e armazenar
os dados quando um produtor publica
• Um consumidor consome dados de um broker em
um deslocamento especificado, ou seja, posição
• O Kafka usa o zookeeper para facilitar a
verificação de integridade, o gerenciamento e a
coordenação
• O zookeeper oferece aos brokers, metadados
sobre os processos em execução no sistema
ARQUITETURA

• Um tópico é um nome de categoria/feed, no qual


os registros são armazenados e publicados. Os
tópicos têm partições e ordem garantida por
partições

• Todos os registros do Kafka são organizados em


tópicos. Aplicativos produtores gravam dados em
tópicos e aplicativos consumidores leem tópicos
PONTOS DE ENTRADA

Implementação personalizada de produtor e


consumidor usando a API do cliente Kafka
• Java, Scala, C++, Python

Conectores Kafka
• LogFile, HDFS, JDBC, ElasticSearch…

Logstash
• Fonte e destino

Outras ferramentas de ingestão ou processamento


que suportam Kafka
• Apache Spark, LinkedIn Gobblin, Apache
Storm…
INTEGRAÇÃO DE DADOS E PROCESSAMENTO
Stream
Source
Real time
Stream stream
Events
Source processing
Central data buffer
Stream
Flush
Source Flush
periodically immediately

No data lost during


downtime (scheduled
and unscheduled) of a Big Files
Hadoop cluster
HDFS Indexed data

Batch Fast data


Kafka buffers protects the processing access
recent data from being lost
(before a daily HDFS snapshot
can backed them up)
REGISTRO DE FLUXO
Considere um broker com três tópicos, no qual cada tópico
possui 8 partições

O produtor envia um registro para a partição 1 no tópico 1 e,


como a partição está vazia, o registro termina no
deslocamento 0
REGISTRO DE FLUXO

O próximo registro é
adicionado à partição 1 e acima
no deslocamento 1, e o próximo
registro no deslocamento 2 e
assim por diante

Esse é um log de confirmação e


cada registro é anexado ao log
e não há como alterar os
registros existentes no log
(imutável). Esse também é o
mesmo deslocamento que o
consumidor usa para
especificar onde iniciar a leitura
USOS DO KAFKA

• Mensageria

• Métricas

• Agregação de logs

• Registros de atividades em sites e aplicações Web

• Operações de TI

• Internet das Coisas


BIBLIOGRAFIA

1. https://www.redhat.com/pt-br/topics/integration/what-is-apache-

kafka#:~:text=O%20Apache%20Kafka%20%C3%A9%20uma,entreg%C3%A1%2Dlos%20a%20v%C3%A1rios

%20clientes

2. https://vepo.medium.com/entendendo-o-kafka-bf64169e421f

3. https://www.infoq.com/br/articles/real-time-api-kafka/

4. https://www.infoq.com/br/articles/apache-kafka-licoes/
COMPUTAÇÃO ESCALÁVEL

Avaliação de desempenho
ROTEIRO

• O que é desempenho?

• Como analisar o desempenho?

• Por que e para que desempenho?

• Pontos de avaliação

• Como medir o desempenho?

• Avaliação x análise
O QUE É DESEMPENHO / COMO ANALISAR?

O que é desempenho?

Medida da capacidade de resposta de um


sistema
COMO ANALISAR DESEMPENHO?

Medições

Análises quantitativas

Métricas de desempenho
POR QUE DESEMPENHO / PARA QUE
DESEMPENHO?

POR QUE?

• Aspecto chave no projeto, compra,


gerenciamento e otimização de sistemas
computacionais

• Exemplo: Sistemas Web são críticos para


a vida cotidiana. Praticamente quase tudo
está na web
POR QUE DESEMPENHO / PARA QUE
DESEMPENHO?

PARA QUE?

• Identificar pontos de contenção e/ou de


desperdício de um sistema
• Avaliar múltiplas alternativas de projeto e/ou
implementação de uma aplicação
• Encontrar a configuração ótima dos
parâmetros de um sistema
• Planejamento de capacidade
• Identificar erros de implementação
POR QUE DESEMPENHO / PARA QUE
DESEMPENHO?
Por que se preocupar com o desempenho?

Por que saber qual a temperatura no final do dia, da


semana, do mês?
IMPORTÂNCIA DA AVALIAÇÃO
Por que se preocupar em avaliar um sistema
• Obtenção do melhor desempenho com custo
reduzido
• O que é o melhor desempenho e o que deve ser
analisado?
• Depende do ponto de vista!!!

Perguntas
• O que o sistema precisa?
• Qual é o tipo de usuário?
• Qual é o objetivo do sistema?
• Como se dá o gerenciamento de recursos?
PONTOS DE AVALIAÇÃO

EXEMPLO

• Tornar um sistema mais rápido

• O que será preciso?

• Descobrir os pontos de atraso

• Propor soluções

• Avaliar as soluções
PONTOS DE AVALIAÇÃO

O QUE VEM A SER A AVALIAÇÃO?

• Período/situação: quando se preocupar com o


desempenho?

• Atores: quem deve ser preocupar?

• Métricas: como medir o desempenho? E o que


medir?

• Confiança: como confiar nas métricas obtidas?


PONTOS DE AVALIAÇÃO

AVALIAR UM SISTEMA (COMPUTACIONAL OU NÃO) É:


• Buscar uma métrica que indique quantidade ou
qualidade, por exemplo, de um serviço prestado

• Determinar a eficiência com a qual um sistema


atinge as necessidades e expectativas de seus
usuários e desenvolvedores para uma dada
aplicação
PONTOS DE AVALIAÇÃO

PARA AVALIAR UM SISTEMA (COMPUTACIONAL


OU NÃO) É PRECISO UMA ANÁLSE DETALHADA:

• Dos recursos do sistema

• Dos gerenciadores

• Dos usuários

• Dos objetivos do sistema e da avaliação


EXEMPLO
EXEMPLO
COMO MEDIR O DESEMPENHO?

EM SISTEMAS COMPUTACIONAIS AS MEDIDAS:

• Não podem ser um fator degenerador

• Devem considerar o domínio da aplicação

• Devem deixar a análise isenta


COMO MEDIR O DESEMPENHO?

TÉCNICAS PARA A MEDIÇÃO

• Aferição

• Protótipos

• Coleta de dados

• Benchmarks

Realizam experimentações no sistema


COMO MEDIR O DESEMPENHO?

TÉCNICAS PARA A MEDIÇÃO

• Modelagem

• Desenvolvimento do modelo

• Soluções para o modelo

Criam abstrações do sistema


COMO MEDIR O DESEMPENHO?

O QUE MEDIR?

• Chama-se variável de resposta

• Depende de diversos enfoques

• Responsividade

• Produtividade

• Utilização
AVALIAÇÃO X ANÁLISE

AVALIAÇÃO
• Obter, produzir e levantar dados sobre uma
determinada entidade

• Exemplo: calcular o consumo de um automóvel


• Utilizar uma técnica para medir a distância
percorrida e o volume de combustível
consumido
AVALIAÇÃO X ANÁLISE

ANÁLISE
• Verificar a precisão, a validade e o significado da
grandeza produzida durante a avaliação

• Exemplo: se a avaliação do automóvel levou a 12


km/litro de álcool, então a análise se preocupa
em se certificar que:
• a metodologia utilizada foi correta
• os números levantados são suficientemente
precisos
• e, então, conclui se o desempenho avaliado é
bom, ruim etc.
BIBLIOGRAFIA

1. ALMEIDA, J. M; Análise e Modelagem de Desempenho, UFMG, 2017

2. SANTANA, M.J., SANTANA, R.H.C., FRANCÊS, C.R.L., Avaliação e Análise de Desempenho

de Sistemas Computacionais: Técnicas e Ferramentas, Publicação Interna ICMC - USP,

1997

3. JAIN, J., The art of Computer Systems Performance Analysis, John Wiley & Sons, Inc., 1996.
COMPUTAÇÃO ESCALÁVEL

Teste de Carga em Aplicações


ROTEIRO

• O que é carga de trabalho?

• Procedimento para carga de trabalho

• Caracterização de carga de trabalho

• Tipos de carga de trabalho

• Teste de carga em aplicações


O QUE É CARGA DE TRABALHO?

Conjunto de todas as informações de entrada


que um sistema recebe durante qualquer
período de tempo determinado

Muito importante no planejamento de


capacidade e na avaliação de sistemas
PROCEDIMENTO PARA A CARGA DE
TRABALHO

DETERMINAR QUE TIPO DE CARACTERISTICA É


IMPORTANTE SER REPRESENTADA

 Depende do objetivo da avaliação

 Exemplo: qual a carga que devemos considerar


para avaliar um sistema computacional?
CARACTERIZAÇÃO DE CARGA DE TRABALHO

NÍVEL DE DETALHE A SER CONSIDERADO

VÁRIAS POSSIBILIDADES:

• Utilizar as requisições mais frequentes


• Considerar os vários tipos de requisições e suas
frequências
• Trace: sequência de requisições com timestamp
• Utilizar valores médios
• Utilizar distribuições de probabilidade
CARACTERIZAÇÃO DE CARGA DE TRABALHO

VERIFICAR A REPRESENTATIVIDADE DA CARGA DE


TRABALHO

TRÊS ASPECTOS IMPORTANTES:

• Taxa de chegada
• Demanda por recurso
• Sequência e demanda por diferentes recursos
• Atualização da carga de trabalho
TIPOS DE CARGA DE TRABALHO

PRECISAMOS AGORA DE UMA FORMA PARA


REPRESENTAR A CARGA DE TRABALHO

Basicamente, duas formas:

• Carga de trabalho Real


• Carga de trabalho Sintética
TIPOS DE CARGA DE TRABALHO

Real
Observada no sistema real em operação
normal

Desvantagens
Vantagem • Não pode ser repetida com
facilidade
• Precisão
• Arquivos de Trace → arquivos
muito grandes
TIPOS DE CARGA DE TRABALHO

Sintética
Carga com características similares às reais

Vantagens: Problema:
• Pode ser repetida de forma • Determinar a
controlada distribuição
• Não necessita de arquivos mais
com dados reais apropriada
• Carga pode ser facilmente para o sistema
modificada em avaliação
• Pode ser transportada para
diferentes sistemas
TESTE DE CARGA EM APLICAÇÕES

Teste de carga é um tipo de teste de desempenho que


simula uma carga do mundo real em qualquer
software, aplicativo ou site em teste

Objetivo: examinar como o sistema se


comportará em condições normais e extremas
de carga geradas por usuários
TESTE DE CARGA EM APLICAÇÕES

POR QUE É IMPORTANTE?

 O teste de carga ajuda a descobrir erros ou


possíveis falhas em diferentes cenários, para que
você possa cuidar deles e corrigi-los muito antes de
finalizar o desenvolvimento de um sistema

 Outros motivos importantes pelos quais a


realização de um teste de carga é fundamental:
 acessibilidade, base de clientes e muitos outros
TESTE DE CARGA EM APLICAÇÕES

BENEFÍCIOS

 Escalabilidade

 Descobrir gargalos antes da implantação

 Reduzir o tempo de inatividade do sistema

 Garantir satisfação do usuário

 Reduzir o custo de falha


BIBLIOGRAFIA

1. Avaliação de Desempenho de Sistemas Computacionais – Regina Helena Carlucci Santana e Marcos José
Santana - Departamento de Sistemas de Computação – ICMC-USP / São Carlos – SP

2. https://acervolima.com/nocoes-basicas-de-teste-de-carga-ferramentas-e-praticas-em-teste-de-software/
COMPUTAÇÃO ESCALÁVEL

Ferramentas para
Teste de Carga
ROTEIRO

• Escolha de Ferramenta
• Teste de estresse x Teste de carga
• Exemplos de ferramentas
ESCOLHA DA FERRAMENTA

 A escolha de uma ferramenta de teste de carga depende


inteiramente das necessidades do seu projeto, como tempo,
orçamento, etc.
TESTE DE ESTRESSE X TESTE DE CARGA

Teste de Carga
 Usado para simular condições normais
 Quantidade de dados utilizada é a mesma estimada para
o dia a dia de trabalho
 Objetivo não é quebrar o sistema

Teste de Estresse
 Testa o comportamento do sistema simulando
condições extremas
 O teste só encerra após ter gerado uma falha no
sistema
 Objetivo é quebrar o sistema, gerar falhas
FERRAMENTAS

Stress Tester
 Oferece uma análise extensa do desempenho de
aplicações Web, além de resultados em formatos de
gráfico
 Fácil de utilizar
 Não precisa de scripts de altíssimo nível
FERRAMENTAS

Jmeter
 Ferramenta de teste open source
 É uma aplicação em Java para testar estresse e
performance
 Objetivo:
 Realizar uma gama de testes, como carregamento,

funcionalidade, estresse, etc.


FERRAMENTAS

BlazeMeter
 A BlazeMeter comercializa uma plataforma comercial de
teste de carga de autoatendimento como serviço (PaaS),
que é compatível com o Apache JMeter
 A BlazeMeter foi fundada em 2011 e foi adquirida pela CA
Technologies em 2016. Em 2021, foi adquirida pela
Perforce
FERRAMENTAS

Gatling
 Gatling é uma solução de teste de carga de código aberto
 Foi projetada para testes de carga contínuos e se integra
ao seu pipeline de desenvolvimento
 Gatling inclui um gravador web e relatórios
FERRAMENTAS

Gatling
 O teste de carga com Gatling permite que você emule
tráfego pesado, obtenha relatórios e encontre possíveis
bugs. Testes de capacidade, testes de imersão ou teste
de estresse podem ser feitos sem muito esforço ao
longo do processo de CI/CD:
 Injetores de carga sob demanda

 Relatórios avançados

 APIs públicas e fonte de dados Grafana

 Integração contínua

 Modo de clustering/Distribuído
BIBLIOGRAFIA

1.https://gatling.io/
2.https://www.primecontrol.com.br/testes-de-estresse-e-carga-conheca-os-
tipos-e-ferramentas/
3.https://guide.blazemeter.com/hc/en-us
4.https://download.cnet.com/Web-Stress-Tester/3000-2085_4-
75316840.html
5.https://jmeter.apache.org/
COMPUTAÇÃO ESCALÁVEL

Estudo de Caso
com JMETER
ROTEIRO

• JMeter
• Plano de Teste
• Exemplo
• Resultados
JMETER

 Multiplataforma e gratuito
 Gera gráficos em CSV, tabelas e gráficos

 Execução distribuída

 Suporta supervisores como:

 HTTP, HTTPS, LDAP, JMS


JMETER

O JMeter simula um grupo de usuários


enviando solicitações para um servidor de
destino e retorna estatísticas, que mostram
o desempenho/funcionalidade do
servidor/aplicativo de destino por meio de
tabelas, gráficos, etc.
PLANO DE TESTE

 Um Plano de Teste pode ser visto como um container


para execução de testes

 Define o que testar e como fazê-lo

 Um plano de teste completo consiste em um ou mais


elementos, como grupos de threads, controladores
lógicos, controladores geradores de amostra,
ouvintes, temporizadores
EXEMPLO

Plano de Teste Web


 Passos
 Iniciar o Jmeter

 Renomear o Plano de Teste

 Adicionar grupo de tópicos

 Adicionar amostrador

 Adicionar ouvinte

 Executar o plano de teste

 Saída gerada
EXEMPLO
Iniciar JMeter
EXEMPLO
Renomear o plano de teste para: Testar Univesp
EXEMPLO
Adicionar grupo de tópicos
EXEMPLO
Adicionar amostrador
EXEMPLO
Adicionar ouvinte
EXEMPLO
Executar plano de teste
EXEMPLO
Resultado
EXEMPLO
Resultado
EXEMPLO
Resultado
BIBLIOGRAFIA

1.https://www.tutorialspoint.com/jmeter/jmeter_overview.htm
2.https://jmeter.apache.org/
3.https://www.loadview-testing.com/pt-br/blog/5-exemplos-de-
teste-de-carga-de-5-jmeter/
4.https://www.devmedia.com.br/teste-de-performance-com-
jmeter/34621
COMPUTAÇÃO ESCALÁVEL

OpenShift – Introdução
e Arquitetura
ROTEIRO
• Introdução
• Arquitetura e componentes
• Camada de infraestrutura
• Camada de serviços
• Nó principal
• Nós de trabalho
• Registro
• Armazenamento persistente
• Camada de roteamento
INTRODUÇÃO

 O OpenShift é uma ferramenta utilizada para


gerenciar containers de software, oferecendo
segurança, monitoramento e controle

 Com a ferramenta podemos:


 criar um ambiente integrado baseado em containers

 implantar aplicações feitas em diversas linguagens

 escalar essas aplicações


ARQUITETURA E COMPONENTES
ARQUITETURA E COMPONENTES

Componentes
 Nodes
 Masters
 Containers
 Pod
 Services
 API Authentication
 Datastore
 Scheduler
 Management/Replication
 Registry
ARQUITETURA E COMPONENTES

Camada de infraestrutura
 Ambiente em que podemos hospedar as aplicações
em servidores físicos, servidores virtuais ou na
nuvem (pública/privada)
ARQUITETURA E COMPONENTES

Camada de serviços
 Responsável por definir os pods e a política de
acesso
 Fornece endereço IP e um nome de host para os
pods
 Conecta aplicações
 Permite balanceamento de carga
ARQUITETURA E COMPONENTES

Nó principal
 Aquele que gerencia o cluster e cuida dos nós
trabalhadores, sendo responsável por:
 API e Autenticação

 Data Stora

 Escalonamento

 Escalabilidade

Nós trabalhadores
 Compostos de pods. Pod é a menor unidade que
pode ser definida, implantada e gerenciada e pode
conter um ou mais containers. Containers são
formados por aplicações + suas dependências
ARQUITETURA E COMPONENTES

Registro
 Salva suas imagens localmente no cluster
 Quando uma nova imagem é enviada para o
registro, este notifica o OpenShift e passa as
informações da imagem
ARQUITETURA E COMPONENTES

Armazenamento persistente
 Local em que os dados são salvos e conectados
aos contêineres.

 Por que precisa?


 Porque os contêineres são efêmeros, o que

significa que quando são reiniciados ou excluídos,


todos os dados salvos são perdidos. Isso vai
evitar qualquer perda de dados
ARQUITETURA E COMPONENTES

Camada de roteamento
 Fornece acesso externo as aplicações no cluster de
qualquer dispositivo
 Fornece também balanceamento de carga e
roteamento automático em torno de pods
BIBLIOGRAFIA

1.https://developer.ibm.com/blogs/openshift-101-architecture/
2.https://medium.com/@raraujo_/entendendo-a-arquitetura-do-
openshift-e-criando-um-cluster-local-ca5f59d9caaf
3.https://docs.microsoft.com/pt-br/azure/openshift/intro-openshift
4.https://redhatbsb.gitbook.io/workshop-openshift/parte-2-openshift
5.https://pensandolinux.com.br/2021/02/14/openshift-iniciando-os-
estudos-red-hat-codeready-containers/
6.https://www.redhat.com/pt-br/technologies/cloud-computing/openshift
7.https://smartworldclub.net/11703119-red-hat-openshift-4-what39s-
new-and-how-to-create-a-cluster
COMPUTAÇÃO ESCALÁVEL

Criação de um
Cluster OpenShift
ROTEIRO

• Pré-requisitos
• Download do OpenShift
• Instalar o OpenShift
• Iniciar o cluster
PRÉ-REQUISITOS

 O OpenShift é uma plataforma como serviço (PaaS)


gratuita, de código aberto, e de desenvolvimento em
nuvem desenvolvida pela Red Hat

 O pré-requisito para instalar o OpenShift como PaaS é:


 uma distribuição Linux instalada no host

 ter o docker instalando no host/desktop/notebook

 Você pode rever algumas matérias das disciplinas


COM380, COM420, nas quais eu destaco a instalação
em configuração do docker em Windows e Linux
DOWNLOAD

 Download do OpenShift Origin


 https://github.com/openshift/origin/releases/downlo

ad/v3.11.0/openshift-origin-client-tools-v3.11.0-
0cbc58b-linux-64bit.tar.gz

 Depois de baixado, temos que descompactar o


arquivo
 tar -xvzf openshift-origin-client-tools-v3.11.0-

0cbc58b-linux-64bit.tar.gz
INSTALAÇÃO

 Entre no diretório
 cd openshift-origin-client-tools-v3.11.0-0cbc58b-

linux-64bit
 Copie os binários kubectl e oc para o diretório
/usr/local/bin

 cd openshift-origin-client-tools-v3.11.0-0cbc58b-
linux-64bit
 cp oc kubectl /usr/local/bin/
INSTALAÇÃO

 Depois executa o comando


 oc version

 E teremos a saída

 oc v3.11.0+0cbc58b
 kubernetes v1.11.0+d4cacc0
 features: Basic-Auth GSSAPI Kerberos SPNEGO
INSTALAÇÃO

 Criação de um arquivo: daemon.jso e permitir o


uso do registro do docker
 pico /etc/docker/daemon.json

{
"insecure-registries" : [ "172.30.0.0/16" ]
}
INICIAR O OPENSHIFT CLUSTER
 Para iniciar o cluster OpenShift é preciso especificar
o IP do host
 oc cluster up –public-hostname=192.168.2.5

 Após a inicialização do servidor, veremos uma saída:

The server is accessible via web console at:


https://your-server-ip:8443

You are logged in as:


User: developer
Password: <any value>

To login as administrator:
oc login -u system:admin
INICIAR O OPENSHIFT CLUSTER
 Logar no cluster como administrador
 oc login -u system:admin

 A saída será como mostrado a seguir

Logged into "https://127.0.0.1:8443" as "system:admin" using existing credentials.

You have access to the following projects and can switch between them with 'oc project ':

default
kube-dns
kube-proxy
kube-public
kube-system
* myproject
openshift
openshift-apiserver
openshift-controller-manager
openshift-core-operators
openshift-infra
openshift-node
openshift-service-cert-signer
openshift-web-console

Using project "myproject".


INICIAR O OPENSHIFT CLUSTER
 Vamos agora mudar para um projeto padrão
como descrito no slide anterior

oc project default

Now using project "default" on server "


https://localhost:8443".
INICIAR O OPENSHIFT CLUSTER

 Verificar o status atual do projeto


In project default on server https://your-server-ip:8443
svc/docker-registry - 172.30.1.1:5000
dc/docker-registry deploys docker.io/openshift/origin-docker-
registry:v3.11
deployment #1 deployed 2 minutes ago - 1 pod
svc/kubernetes - 172.30.0.1:443 -> 8443
svc/router - 172.30.94.157 ports 80, 443, 1936
dc/router deploys docker.io/openshift/origin-haproxy-router:v3.11
deployment #1 deployed 2 minutes ago - 1 pod
View details with 'oc describe /' or list everything with 'oc get all'.
BIBLIOGRAFIA

1.https://www.okd.io/#getting-started
2.https://pensandolinux.com.br/2021/02/14/openshift-iniciando-os-estudos-
red-hat-codeready-containers/
3.https://www.ibm.com/br-pt/cloud/openshift/openshift-tutorials
4.https://www.howtoforge.com/how-to-install-and-configure-openshift-origin-
paas-server-on-ubuntu-2004/
5.https://redhatbsb.gitbook.io/workshop-openshift/parte-2-openshift
COMPUTAÇÃO ESCALÁVEL

Deploy de Aplicações com


OpenShift
ROTEIRO

• Criar Projeto

• Acesso ao Console Web

• Deploy de Aplicação

• Acessar Aplicação
CRIAR PROJETO

Para criar o projeto temos que logar no cluster com o


usuário developer

Coloque para login e senha: developer

oc login
Authentication required for
https://127.0.0.1:8443 (openshift)
Username: developer
Password: developer
Login successful.

You have one project on this server:


"myproject"
Using project "myproject".
CRIAR PROJETO

Comando para a criação de um projeto:

oc new-project dev --display-name="Project -


Dev" --description="My Project"
ACESSO AO CONSOLE WEB
Para acessar o console Web do OpenShift basta digitar no browser
https://localhost:8443

Utilize como login e senha: developer


ACESSO AO CONSOLE WEB
No lado direto da tela, clique no botão Create Project
 Name: my-project
 Display Name: Meu Projeto
 Description: Meu primeiro projeto
DEPLOY DE APLICAÇÃO

PASSO A PASSO

• Logar com usuário e senha: developer

 oc login
Authentication required for https://127.0.0.1:8443 (openshift)
Username: developer
Password:
Login successful.
You have access to the following projects and can switch between them
with 'oc project ':
* dev
my-project
myproject
Using project "dev".
DEPLOY DE APLICAÇÃO
PASSO A PASSO

• Ainda no terminal digite:

 oc project my-project
Now using project "my-project" on server "https://127.0.0.1:8443".

• Para ver o status do projeto

 oc status
In project My Project (my-project) on server https://127.0.0.1:8443
You have no services, deployment configs, or build configs.
Run 'oc new-app' to create an application.
DEPLOY DE APLICAÇÃO

PASSO A PASSO

• Deploy da aplicação

 oc my-project deployment-example
--> Found image da61bb2 (4 years old) in image stream "my-project/deployment-example" under tag
"latest" for "deployment-example"
* This image will be deployed in deployment config "deployment-example"
* Port 8080/tcp will be load balanced by service "deployment-example"
* Other containers can access this service through the hostname "deployment-example"
* WARNING: Image "my-project/deployment-example:latest" runs as the 'root' user which may not be
permitted by your cluster administrator
--> Creating resources ...
deploymentconfig.apps.openshift.io "deployment-example" created
service "deployment-example" created
--> Success
Application is not exposed. You can expose services to the outside world by executing one or more
of the commands below:
'oc expose svc/deployment-example'
Run 'oc status' to view your app.
DEPLOY DE APLICAÇÃO

PASSO A PASSO

• Status do Deploy

 oc status
In project My Project (my-project) on server https://your-server-
ip:8443
svc/deployment-example - 172.30.87.146:8080
dc/deployment-example deploys istag/deployment-example:latest
deployment #1 deployed 36 seconds ago - 1 pod
2 infos identified, use 'oc status --suggest' to see details.
DEPLOY DE APLICAÇÃO

PASSO A PASSO

• Status do serviço

 oc get svc

NAME TYPE CLUSTER-IP EXTERNAL-IP


PORT(S) AGE
deployment-example ClusterIP 172.30.87.146 8080/TCP
1m
DEPLOY DE APLICAÇÃO

PASSO A PASSO

• Informações em detalhes para o serviço


Name: deployment-example
Namespace: my-project
Labels: app=deployment-example
Annotations: openshift.io/generated-by=OpenShiftNewApp
Selector: app=deployment-example,deploymentconfig=deployment-example
Type: ClusterIP
IP: 172.30.87.146
Port: 8080-tcp 8080/TCP
TargetPort: 8080/TCP
Endpoints: 172.17.0.10:8080
Session Affinity: None
Events:
DEPLOY DE APLICAÇÃO

PASSO A PASSO

• Verificar os pods

 oc get pods

NAME READY
STATUS RESTARTS AGE
deployment-example-1-b9prf 1/1
Running 0 2m
DEPLOY DE APLICAÇÃO

PASSO A PASSO

• Exportar a aplicação para acesso externo

 oc expose service/deployment-example

route.route.openshift.io/deployment-example exposed
DEPLOY DE APLICAÇÃO

PASSO A PASSO

• Informações de rota

 oc get routes

NAME HOST/PORT PATH


SERVICES PORT TERMINATION WILDCARD
deployment-example deployment-example-my-project.your-server-ip.nip.io
deployment-example 8080-tcp
ACESSAR APLICAÇÃO

ABRA O BROWSER COM UM IP COMO ESTE

http://172.30.106.225:8080/
BIBLIOGRAFIA

1. https://www.okd.io/#getting-started

2. https://pensandolinux.com.br/2021/02/14/openshift-iniciando-os-estudos-red-hat-codeready-containers/

3. https://www.ibm.com/br-pt/cloud/openshift/openshift-tutorials

4. https://www.howtoforge.com/how-to-install-and-configure-openshift-origin-paas-server-on-ubuntu-2004/

5. https://redhatbsb.gitbook.io/workshop-openshift/parte-2-openshift

Você também pode gostar