Baixe Introdução Programação Paralela E Cluster e outras Notas de estudo em PDF para Cultura, somente na Docsity!
Introdução ao Processamento Paralelo e ao Uso de
Clusters de Workstacions em Sistemas GNU/LINUX
Parte I: Filosofia
Laboratório de Meios Porosos e Propriedades Termofísicas - LMPT
Versão 0.
12 de novembro de 2002
Resumo
O termo cluster de workstacions, refere-se a utilização de di-
versos computadores conectados em rede para realização de pro-
cessamento paralelo. Este artigo introduz os termos e conceitos
necessários ao entendimento e uso do processamento paralelo e de
clusters em sistemas GNU/LINUX. Descreve-se os direntes tipos
de processamento paralelo em máquina multi-processadas (SMP)
e em cluster de workstacions. A seguir, apresenta-se as biblio-
tecas para implementação de multi-processos, multi-threads, e os
sistemas de troca de mensagens como PVM e MPI. Da-se ênfase
a linguagem C/C++ e inclue-se um conjunto de links e referências
para documentos externos, facilmente obtidos na internet.
Sumário
1 Introdução 2
2 Objetivo e conceito de processamento paralelo 3
3 O que você precisa saber 3
4 Tipos de processamento paralelo 3
4.1 Processamento paralelo com Swar
(Simd Withn a Register).............. 3
4.2 Processamento paralelo com SMP
(Symetric Multi Processor)............. 3
4.3 Processamento paralelo com cluster Beowulf... 3
4.4 Processamento paralelo com cluster de
workstation..................... 4
4.5 Processamento paralelo em um cluster com MOSIX 4
5 Bibliotecas para desenvolvimento de programas utili-
zando processamento paralelo 5
5.1 Processos...................... 5
5.2 Threads....................... 5
5.3 PVM (Parallel Virtual Machine).......... 5
5.4 MPI (Message Passing Interface).......... 5
∗Este documento pode ser livremente copiado, segundo as regras GPL. O artigo
“Introdução ao Processamento Paralelo e ao Uso de Clusters de Workstacions em Sistemas GNU/LINUX Parte II: Processos e Threads”, complementa este artigo abordando, mais profundamente o uso de processos e threads.
6 Exemplo de código comum 6
7 Exemplo de código usando múltiplos processos 6
8 Exemplo de código usando múltiplas threads 7
9 Exemplo de código usando PVM 8
10 Exemplo de código usando MPI 9
10.1 Exemplo de código usando MPI_1.0........ 9
10.2 Exemplo de código usando MPI_1.1........ 10
10.3 Exemplo de código usando MPI_2......... 10
11 Como se aprofundar
(leituras aconselhadas) 10
11.0.1 Iniciar com os HOWTOS.......... 10
11.0.2 Verificar a Home Page do Beowulf..... 10
11.0.3 Bibliotecas PVM, MPI e Threads..... 11
12 Conclusões 11
A Apêndice A- Hardware para processamento paralelo 12
B Apêndice B- Glossário 12
C Apêndice C - Roteiro para paralelização e otimização
de algoritmos 13
D Apêndice - HOWTO INSTALL MOSIX 13
1 Introdução
Um cluster de workstation é um conjunto de computadores (he-
terogêneos ou não) conectadas em rede para o desenvolvimento
de processamento paralelo. Ou seja, as máquinas são conectadas
via rede para formar um único computador , [13]. Embora pou-
cas tarefas possam ser paralelizadas com facilidade, um cluster de
computadores é útil para uma enorme quantidade de problemas ci-
entíficos.
Deve-se considerar ainda que paralelizar algoritmos é um ramo
bastante inexplorado e de importância vital para a indústria de in-
formática nos próximos anos [13].
Como exemplo, pode-se citar a utilização de modelos de gás em
rede para simulação de propriedades físicas dos materiais. Como
estes modelos são massissamente paralelizáveis, pode-se, com o
uso de cluster, aumentar o desempenho dos algoritmos e possibi-
litar o trabalho com representações tridimensionais de elevada di-
mensão, [10]. O mesmo ocorre com os métodos para determinação
das configurações de equilíbrio e de permeabilidade relativa, [3, 2].
Veja diagrama de um cluster na Figura 1.
Figura 1: Diagrama de um cluster.
O projeto pioneiro em cluster de computadores foi desenvolvido
no CESDIS (Center of Excellence in Space Data and Information
Sciences) em 1994. Contava com 16 máquinas 486 rodando
GNU/Linux. O nome dado ao primeiro cluster foi BEOWULF.
O princípio de funcionamento é simples. O servidor divide as
tarefas em suas partes independentes (ditas concorrentes), a seguir,
distribuí estas tarefas entre os vários computadores que fazem parte
do cluster. As tarefas são processadas e então os resultados são
enviados para o servidor.
Para que o sistema funcione é necessário um servidor, vários
clientes, uma biblioteca para troca de mensagens e o hardware para
conexão via rede dos diversos computadores.
- O servidor distribue o processamento para as diversas máqui-
nas clientes (nós). Observe na Figura 1 que o servidor envia
e recebe mensagens (e dados) para os diversos clientes pas-
sando pelo switch.
- O hardware da rede (placas de rede, switch, cabos) deve ter
qualidade e capacidade para transferir os dados do servidor
para os clientes com a menor perda de tempo possível (latên-
cia).
- Cada cliente recebe as mensagens e um conjunto de dados a
serem processados. Concluído o processamento, os resultados
são enviados para o servidor.
- A biblioteca de troca de mensagens deve conter um conjunto
de funções que serão utilizadas para distribuir o processa-
mento entre as diversas máquinas do cluster.
Exemplos de cluster:
- O Avalon (http://swift.lanl.gov/avalon/) é um clus-
ter de 140 máquinas Alpha 533 MHz, localizado no Labo-
ratório Nacional de Los Alamos, nos Estados Unidos. Esse
computador já foi o 113o^ no TOP500, a lista das 500 máqui-
nas mais rápidas do mundo. O fato de o Avalon ter custado
uma fração do preço de seus concorrentes próximos no ran-
king, mesmo usando máquinas de alta qualidade, é um tes-
temunho da vantagem da solução de processamento pesado
usando clusters. O avalon é formado com Switch 3com su-
perstack II 3900 36portas-fast ethernet switch. Inicialmente
contava com 70 máquinas Alpha 533Mhz, obtendo o mesmo
desempenho de um computador paralelo com 64 processa-
dores a 195Mhz (que custava na época 1.8 milhões de do-
lares). Usa o GNU/Linux da Red Hat, o pacote de compila-
ção egcs-1.1b e a biblioteca MPICH. Os autores indicam a
necessidade de um sistema de cooling (resfriamento) de me-
lhor qualidade em cada máquina, além de uma rede elétrica
dedicada [http://www.cnls.lanl.gov/avalon/FAQ], adaptado de
[13]. Veja na Figura 2 um cluster.
Figura 2: Cluster do Numerical Aerospace Simulation Facility
NASA Ames Research Center.
Figura 4: Exemplo de cluster estilo Beowulf
(http://loki-www.lanl.gov).
Figura 5: Cluster da University Koblenz-Landau Institute of
Physics.
4.4 Processamento paralelo com cluster de
workstation
Um cluster de workstation é um conjunto de computadores com-
pletos (com teclado, monitor, mouse), conectados em rede, e que
cumprem duas funções: i) o uso diário, com diversos tipos de pro-
gramas como processadores de texto e planilhas, ii) o uso para pro-
cessamento paralelo pesado no final do dia e/ou nos fins de semana.
A Figura 6, mostra um exemplo de cluster de workstation.
Requisitos: As máquinas devem ser completas e independentes.
Requer o uso de uma biblioteca de troca de mensagens como
PVM ou MPI.
Vantagens: Possibilita o uso das máquinas por diferentes usuários
para realização de suas tarefas rotineiras.
Desvantagens: Como vários usuários estão utilizando os proces-
sadores para outras tarefas, o desempenho do sistema é re-
duzido. Na prática reduz o uso do cluster ao final do dia e
nos fins de semana. Tem um custo maior por máquina e mais
problemas com a manutenção do sistema.
Figura 6: Exemplo de um “ cluster de workstation” (Distribu-
ted Computing Laboratory, Department of Mathematical Sciences,
Cameron University, Lawton).
4.5 Processamento paralelo em um cluster com
MOSIX
Segundo o site do MOSIX, http://www.mosix.com, o MOSIX
é um adendo ao kernel do GNU/LINUX que adiciona ao mesmo
capacidades de computação com cluster. Possibilitando que as es-
tações do cluster, baseadas em X86/Pentium/AMD, trabalhem de
forma cooperativa, como sendo um único sistema.
A migração dos processos entre as várias máquinas do cluster é
automática. Isso permite que programas antigos funcionem num
ambiente de cluster com pouquíssimas alterações, [13].
Características do MOSIX: Balanceamento dinâmico e inte-
ligente de carga, uso com cluster heterogêneo, transparência,
escabilidade, descentralização e autonomia dos nós. Migração
preemptiva dos processos com uso de algoritmos probabilísticos.
Comunicação entre núcleos eficiente, controle descentralizado,
[http://www.ppgia.pucpr.br/~almendes/DIPC_MOSIX/
ppframe.htm].
Requisitos: Requer a recompilação do kernel com a inclusão do
Mosix ou instalação de kernel em pacote (como os pacotes
rpm do GNU/Linux/RedHat). O site do Mosix apresenta in-
formações detalhadas de como instalar o Mosix.
Vantagens: O trabalho de programação é reduzido, exigindo ape-
nas a implementação dos mecanismos de troca de mensagens
entre os diferentes processos. Otimização do uso das máqui-
nas do cluster com a migração automática dos processos.
Desvantagens: Exige a recompilação do kernel.
5 Bibliotecas para desenvolvimento de
programas utilizando processamento
paralelo
1
Os programas podem ser desenvolvidos utilizando-se processos
(5.1), threads (5.2), ou sistemas de troca de mensagens PVM (5.3),
MPI(5.4).
Os dois grandes padrões para troca de mensagens em clusters,
são o Paralel Virtual Machine (PVM) e o Message Passing Inter-
face (MPI). O PVM é o padrão mais antigo, é realmente o nome de
uma biblioteca. O MPI é a novidade na área, é um padrão com
várias implementações criadas principalmente por universidades
e algumas suportadas comercialmente por empresas (adaptado de
[13]).
5.1 Processos
De um modo geral, os computadores com sistemas operacionais
multi-tarefa disponibilizam um conjunto de funções para divisão
e compartilhamento do processador e da memória. Estes sistemas
costumam disponibilizar chamadas ao kernel que possibilitam a
criação de múltiplos processos. Se a máquina tem mais de um pro-
cessador, o sistema operacional distribui os processos pelos pro-
cessadores.
No GNU/Linux e nas variantes do Unix, um processo pode ser
clonado com a função fork(). A comunicação entre os processos é
feita de forma simplificada com o uso de pipes.
Requisitos: Requer o aprendizado do uso das instruções fork
(para clonar processos) e pipe (para comunicação entre os
processos).
Vantagens: Pode ser utilizado com Mosix, não sendo necessário
acrescentar mecanismos de distribuição dos processos.
Desvantagens: O Mosix só é disponível na plataforma GNU/LI-
NUX.
5.2 Threads
Threads são múltiplos caminhos de execução que rodam con-
correntemente na memória compartilhada e que compartilham os
mesmos recursos e sinais do processo pai. Uma thread é um pro-
cesso simplificado, mais leve ou “light”, custa pouco para o sistema
operacional, sendo fácil de criar, manter e gerenciar.
O padrão de implementação de threads é o POSIX 1003.1c thre-
ads standard.
Requisitos: Requer o conhecimento da biblioteca de programação
com threads (também conhecida como PThreads ).
(^1) Existem várias outras opções de gerenciamento e controle da memória e dos
processos (como o System V Shared Memory). De uma maneira geral, quanto maior a eficiência desejada, maior a complexidade dos modelos a serem utilizados. Você vai ter de aprender conceitos como atomicidade, volatilidade, travamento de memória, gerenciamento de cache. A dica é iniciar o desenvolvimento de softwares com processamento paralelo utilizando threads, posteriormente, pode-se adotar um sistema mais complexo e com maior desempenho.
Vantagens: Em poucas palavras é o pacote definitivo para o de-
senvolvimento de programação em larga escala no Linux, [7].
Relativamente fácil de programar. O GNU/Linux tem total
suporte ao Pthread s.
Desvantagens: Não pode ser utilizado com MOSIX.
Veja uma introdução sobre threads em http://centaurus.
cs.umass.edu/~wagner/threads_html/tutorial.html, um
conjunto de links em http://pauillac.inria.fr/~xleroy/
linuxthreads/, descrições adicionais nas referências [12, 4, 16,
14, 20, 18]. Veja um exemplo de uso de threads na seção 8.
5.3 PVM (Parallel Virtual Machine)
É a biblioteca mais utilizada para processamento distribuído. É
o padrão de fato da indústria de software.
O PVM se baseia em duas primitivas básicas: i) envie mensa-
gem e ii) receba mensagem. É de fácil utilização, mas não é tão
poderoso quando comparado com o MPI.
O usuário deve configurar as máquinas para que sejam o mais
idênticas possível, facilitando a manutenção e estabelecendo uma
relação de confiança entre elas. Usar rhosts e rsh é a forma mais
simples de conseguir isso. O usuário roda o gerenciador do PVM,
adiciona máquinas ao cluster e depois simplesmente executa o pro-
grama feito usando as bibliotecas PVM. Veja mais detalhes em
[17, 7, 12, 21] e exemplo de código na seção 9.
Requisitos: Para o desenvolvimento dos programas é necessário
conhecer a biblioteca PVM. É um sistema explicito, ou seja,
cabe ao programador dividir as tarefas através da troca de
mensagens.
Vantagens: Possibilita o uso do processamento distribuído. É o
mais utilizado. Alguns programas de engenharia e matemá-
tica geram código automaticamente para o PVM.
Desvantagens: Não é mais o padrão. O desenvolvimento dos pro-
gramas fica bem mais complicado quando comparado com th-
reads.
5.4 MPI (Message Passing Interface)
É um método que inclui conceitos novos como rank (cada pro-
cesso tem uma identificação única, crescente), group (conjunto or-
denado de processos) e communicator (uma coleção de grupos),
que permitem um gerenciamento mais complexo (e inteligente) do
uso de cada máquina do cluster.
O MPI tem opções mais avançadas (que o PVM), como envio
de mensagens broadcast (para todas as máquinas do cluster) e mul-
ticast (para um grupo específico de máquinas), assim como um
melhor controle sobre o tratamento que cada mensagem terá ao ser
recebida por outro ponto do cluster. A configuração do MPI de-
pende da implementação utilizada e algumas delas chegam a insta-
lar front-ends para compiladores em C e Fortran, mas a forma geral
de uso é semelhante.
Veja maiores detalhes e exemplo na seção 10.
Requisitos: Requer o conhecimento de um sistema bastante com-
plexo de troca de mensagens, o MPI. É um método explicito.
In. close () ; //fecha conexão
cout < < " Valor estimado de pi = " < < pi < < endl ; } //----------------------- //se for o processo filho //----------------------- else { double pi = 0; cout < < " Pid filho = " < < Pid << " iproc = " << iproc < < endl ; pi = process ( iproc , intervalos , nproc ); cout < < " pi filho = " < < pi < < endl ;
close ( Fd [0]) ; //fecha o pipe Out. attach ( Fd [1]) ; //conecta para escrita Out < < pi < < endl ; //escreve Out. close () ; //fecha conexão } return 0; }
//-----------------------Função process double process ( int iproc , double intervalos , int nproc ) { register double width , localsum ; width = 1.0 / intervalos ; localsum = 0; for ( int i = iproc ; i < intervalos ; i += nproc ) { register double x = ( i + 0.5) * width ; localsum += 4.0 / (1.0 + x * x); }
localsum = width ; return (( new double ( localsum ))); }
_Informações:
O processo pai tem Pid=0, setado na saída da função fork. Cada processo filho tem um Pid != 0._
Para identificar de forma mais clara os processos, foi criada a variavel iproc, que assume o valor 0 para o processo pai e 1,2,3... sucessivamente para os filhos.
_Saída:
[andre@mercurio Processos]$ ./a.out 1000 4 ./a.out intervalos =1000 nproc= Fd[0]= 3 Fd[1]= 4 Pid filho = 12545 iproc = 1 pi filho = 0. Pid filho = 12546 iproc = 2 Pid filho = 12547 iproc = 3 pi filho = 0. [andre@mercurio Processos]$ Pid pai = 0 iproc = 0 pi pai = 0. pi filho = 0. Valor estimado de pi = 3._
_Para compilar:
g++ processos4.cpp -o processos_
8 Exemplo de código usando múltiplas th-
reads
Apresenta-se nesta seção um exemplo^4 de programa usando th-
reads em C.
Para compilar este exemplo use:
g++ -v exemplo-thread.cpp -lpthread -D_REENTRANT.
O programa inicia incluindo as bibliotecas de C e criando al-
gumas variáveis globais. A variável que deve ser compartilhadas
é pi, a mesma foi declarada com volatile. Cria uma variável mu-
tex ( pthread_mutex pi_lock; ), que será utilizada para bloquear a
parte do código que não pode ser executada ao mesmo tempo pelas
duas (ou mais) threads. A seguir, monta uma função separada para
a seção que tem código concorrente (paralelizado). Por padrão,
a função deve retornar void* e receber void* ( void* FunçãoTh-
read(void*arg) ). Dentro de main(), Inicializa a variável mutex
( pthread_mutex_init(&pi_lock,val) e cria as diferentes threads
( pthread_t t1,t2,...,tn; ). Dispara a execução de cada thread usando
chamadas a pthread_create(&t1,NULL,process,&arg). A fun-
ção pthread_join(thread,&retval) é usada para esperar o encer-
ramento da thread e obter o valor de retorno da função process
executada pela thread. Observe que você deve usar pthread_join
para evitar que o programa principal encerre sua execução antes
das threads terem sido concluídas.
Observe dentro da função process, o uso do bloquador de
acesso (o mutex) usando pthread_mutex_lock(&pi_lock) e pth-
read_mutex_unlock(&pi_lock).
Listing 3: Determinação de pi usando múltiplas threads.
#include < stdio .h > #include < stdlib .h > #include " pthread .h"
volatile double pi = 0.0; volatile double intervals ; pthread_mutex_t pi_lock ;
//Função thread void * process ( void * arg ) { register double width , localsum ; register int i; register int iproc = (*(( char *) arg ) - ’0 ’);
width = 1.0 / intervals ; localsum = 0; for ( i = iproc ; i < intervals ; i += 2) { register double x = ( i + 0.5) * width ; localsum += 4.0 / (1.0 + x * x); }
localsum *= width ;
/trava acesso a esta parte do código, altera pi, e destrava/ pthread_mutex_lock (& pi_lock ); pi += localsum ;
(^4) Este exemplo obedece o padrão POSIX, podendo ser utilizado em outras plata- formas (como Windows).
pthread_mutex_unlock (& pi_lock ); return ( NULL ); }
int main ( int argc , char * argv []) { pthread_t thread0 , thread1 ; void * retval ;
intervals = atoi ( argv [1]) ;
/* Inicializa a variável mutex*/ pthread_mutex_init (& pi_lock , NULL );
/* Executa duas threads */ if ( pthread_create (& thread0 , NULL , process , ( void *) "0") || pthread_create (& thread1 , NULL , process , ( void *) "1")) { fprintf ( stderr , "%s: cannot make thread \n" , argv [0]) ; exit (1) ; }
/* Join espera as threads terminarem, o retorno é armazenado em retval */ if ( pthread_join ( thread0 , & retval ) || pthread_join ( thread1 , & retval )) { fprintf ( stderr , "%s: thread join failed \n" , argv [0]) ; exit (1) ; }
printf ( " Estimation of pi is %f\n" , pi ); return 0; }
//g++ -v exemplo-thread.cpp -lpthread -o exemplo-thread
9 Exemplo de código usando PVM
5
PVM (Parallel Virtual Machine) is a freely-available, porta-
ble, message-passing library generally implemented on top of
sockets. It is clearly established as the de-facto standard for
message-passing cluster parallel computing. PVM supports single-
processor and SMP Linux machines, as well as clusters of Li-
nux machines linked by socket-capable networks (e.g., SLIP, PLIP,
Ethernet, ATM). In fact, PVM will even work across groups of ma-
chines in which a variety of different types of processors, configu-
rations, and physical networks are used - Heterogeneous Clusters
- even to the scale of treating machines linked by the Internet as a
parallel cluster.
PVM also provides facilities for parallel job control across a
cluster. Best of all, PVM has long been freely available (currently
from http://www.epm.ornl.gov/pvm/pvm_home.html), which has
led to many programming language compilers, application libra-
ries, programming and debugging tools, etc., using it as their
"portable message-passing target library." There is also a network
newsgroup, comp.parallel.pvm.
It is important to note, however, that PVM message-passing
(^5) O material que segue é uma cópia parcial da referencia [7].
calls generally add significant overhead to standard socket ope-
rations, which already had high latency. Further, the message
handling calls themselves do not constitute a particularly "fri-
endly" programming model.
Using the same Pi computation example, the version using C
with PVM library calls is:
Listing 4: Determinação de pi usando PVM.
#include < stdlib .h > #include < stdio .h > #include < pvm3 .h > #define NPROC 4
main ( int argc , char * argv []) { register double lsum , width ; double sum ; register int intervals , i; int mytid , iproc , msgtag = 4; int tids [ NPROC ]; /* array of task ids */
/* enroll in pvm */ mytid = pvm_mytid () ; /* Join a group and, if I am the first instance, iproc=0, spawn more copies of myself */ iproc = pvm_joingroup (" pi ");
if ( iproc == 0) { tids [0] = pvm_mytid () ; pvm_spawn (" pvm_pi " , & argv [1] , 0 , NULL , NPROC -1 , & tids [1]) ; }
/* make sure all processes are here */ pvm_barrier (" pi " , NPROC );
/* get the number of intervals */ intervals = atoi ( argv [1]) ; width = 1.0 / intervals ; lsum = 0.0; for ( i = iproc ; i < intervals ; i += NPROC ) { register double x = ( i + 0.5) * width ; lsum += 4.0 / (1.0 + x * x); }
/* sum across the local results & scale by width */ sum = lsum * width ; pvm_reduce ( PvmSum , & sum , 1 , PVM_DOUBLE , msgtag , " pi " , 0) ;
/* have only the console PE print the result */ if ( iproc == 0) { printf (" Estimation of pi is %f\n" , sum ); } /* Check program finished, leave group, exit pvm */ pvm_barrier (" pi " , NPROC ); pvm_lvgroup (" pi "); pvm_exit () ; return (0) ; }
10.2 Exemplo de código usando MPI_1.
The second MPI version uses collective communication (which,
for this particular application, is clearly the most appropriate):
Listing 6: Determinação de pi usando MPI 1.1.
#include < stdlib .h > #include < stdio .h > #include < mpi .h >
main ( int argc , char * argv []) { register double width ; double sum , lsum ; register int intervals , i; int nproc , iproc ; if ( MPI_Init (& argc , & argv ) != MPI_SUCCESS ) exit (1) ; MPI_Comm_size ( MPI_COMM_WORLD , & nproc ); MPI_Comm_rank ( MPI_COMM_WORLD , & iproc );
intervals = atoi ( argv [1]) ; width = 1.0 / intervals ; lsum = 0;
for ( i= iproc ; i < intervals ; i += nproc ) { register double x = ( i + 0.5) * width ; lsum += 4.0 / (1.0 + x * x); } lsum *= width ; MPI_Reduce (& lsum , & sum , 1 , MPI_DOUBLE , MPI_SUM , 0 , MPI_COMM_WORLD );
if ( iproc == 0) { printf (" Estimation of pi is %f\n" , sum ); } MPI_Finalize () ; return (0) ; }
10.3 Exemplo de código usando MPI_
The third MPI version uses the MPI 2.0 RMA mechanism for
each processor to add its local lsum into sum on
processor 0:
Listing 7: Determinação de pi usando MPI 2.0.
#include < stdlib .h > #include < stdio .h > #include < mpi .h >
main ( int argc , char * argv []) { register double width ; double sum = 0 , lsum ; register int intervals , i; int nproc , iproc ; MPI_Win sum_win ;
if ( MPI_Init (& argc , & argv ) != MPI_SUCCESS ) exit (1) ; MPI_Comm_size ( MPI_COMM_WORLD , & nproc ); MPI_Comm_rank ( MPI_COMM_WORLD , & iproc ); MPI_Win_create (& sum , sizeof ( sum ) , sizeof ( sum ) ,0 , MPI_COMM_WORLD , & sum_win ); MPI_Win_fence (0 , sum_win );
intervals = atoi ( argv [1]) ; width = 1.0 / intervals ;
lsum = 0;
for ( i= iproc ; i < intervals ; i += nproc ) { register double x = ( i + 0.5) * width ; lsum += 4.0 / (1.0 + x * x); } lsum *= width ; MPI_Accumulate (& lsum , 1 , MPI_DOUBLE , 0 , 0 ,1 , MPI_DOUBLE , MPI_SUM , sum_win ); MPI_Win_fence (0 , sum_win );
if ( iproc == 0) { printf (" Estimation of pi is %f\n" , sum ); } MPI_Finalize () ; return (0) ; }
It is useful to note that the MPI 2.0 RMA mechanism very nea-
tly overcomes any potential problems with the corresponding data
structure on various processors residing at different memory lo-
cations. This is done by referencing a "window" that implies the
base address, protection against out-of-bound accesses, and even
address scaling. Efficient implementation is aided by the fact that
RMA processing may be delayed until the next MPI_Win_fence.
In summary, the RMA mechanism may be a strange cross between
distributed shared memory and message passing, but it is a very
clean interface that potentially generates very efficient communi-
cation.
11 Como se aprofundar
(leituras aconselhadas)
7
11.0.1 Iniciar com os HOWTOS
- Beowulf Howto : Um como fazer, que descreve uma série de
conceitos e técnicas para implementação de um cluster
(http://www.sci.usq.edu.au/staff/jacek/beowulf/BDP).
- Linux Parallel Processing HOWTO : Um como fazer, que
descreve três tipos de processamento paralelo (swar, SMP,
cluster) e conceitos básicos de cluster (http://yara.ecn.
purdue.edu/~pplinux/PPHOWTO/pphowto.html).
- C++ Programming Howto : Um como fazer que descreve
algumas características da linguagem C++, exemplos de uso
da STL.
11.0.2 Verificar a Home Page do Beowulf
- Beowulf Homepage (http://www.beowulf.org).
- Beowulf Installation and Administration HOWTO
(http://www.sci.usq.edu.au/staff/jacek/beowulf/
BDP).
(http://beowulf-underground.org).
(^7) Dica: Dê preferencia para material em PDF, é fácil de ler no micro, imprimir com qualidade e possibilita a abertura de links da internet. É universal (Windows/- Mac/Unix/Linux).
- Extreme Linux (http://www.extremelinux.org).
- Extreme Linux Software from Red Hat
(http://www.redhat.com/extreme).
- Building a Beowulf System (http://www.cacr.caltech.
edu/beowulf/tutorial/building.html).
- Programas na página do Beowulf {http://beowulf.gsfc.
nasa.gov/software/software.html}
- Jacek’s Beowulf-utils {ftp://ftp.sci.usq.edu.au/pub/
jacek/beowulf-utils}
- bWatch - cluster monitoring tool
{http://www.sci.usq.edu.au/staff/jacek/bWatch}
11.0.3 Bibliotecas PVM, MPI e Threads
- PVM - Parallel Virtual Machine
{http://www.epm.ornl.gov/pvm/pvm_home.html}
- LAM/MPI (Local Area Multicomputer /
Message Passing Interface
{http://www.mpi.nd.edu/lam}
(http://www.humanfactor.com/pthreads/).
12 Conclusões
O uso do processamento paralelo em um cluster de workstation
é uma ferramenta extremamente poderosa, possibilitando o desen-
volvimento de simulações avançadas em sistemas de baixo custo.
Como visto, os computadores podem ser utilizados para processa-
mento comum de dia e para processamento pesado a noite e nos
finais de semana, aproveitando melhor o parque de máquinas ins-
taladas.
Os programadores precisam aprender os conceitos básicos de
processamento paralelo e as diferentes formas de distribuição do
processsamento (processos, threads, PVM, MPI). Os conceitos bá-
sicos destes sistemas, um pequeno exemplo e referências externas
foram apresentados.
O mecanismo mais fácil de desenvolver processamento paralelo
envolve a utilização de multiplas threads, e a seguir multiplos-
processos sendo aconselhável iniciar com estes mecanismos.
Posteriormente, pode-se trabalhar com bibliotecas especializadas
como PVM e MPI. Em ambos os casos procure utilizar uma bibli-
oteca padrão e multi-plataforma.
Referências
[1] André Duarte Bueno. Introdução ao Processamento Paralelo
e ao Uso de Clusters, Parte I: Filosofia , 2002.
[2] André Duarte Bueno, Fabio Santana Magnani, and Paulo Ce-
sar Philippi. Método para determinação da permeabilidade
relativa de rochas reservatório de petróleo através da análise
de imagens reconstruídas. page 12, Caxambú - MG - Brasil,
2002. CIT02-0672.
[3] André Duarte Bueno and Paulo Cesar Philippi. Modelo do
grafo de conexão serial para determinação da permeabilidade
de rochas reservatório de petróleo. page 12, Caxambú - MG
- Brasil, 2002. CIT02-0668.
[4] David R. Butenhof. Programming with POSIX(R) Threads.
Addison-Wesley, 1987.
[5] Daniel Ridge Daniel Savarese Donald Becker Chance Res-
chke, Thomas Sterling and Phillip Merkey. A design study of
alternative network topologies for the beowulf parallel works-
tation. Fifth IEEE International Symposium on High Perfor-
mance Distributed Computing , 1996.
[6] Phillip Merkey Thomas Sterling Becker Daniel Ridge, Do-
nald Becker and Phillip Merkey. Harnessing the power of
parallelism in a pile-of-pcs. IEEE Aerospace , 1997.
[7] Hank Dietz. Linux Parallel Processing HOWTO.
http://yara.ecn.purdue.edu/ pplinux/PPHOW-
TO/pphowto.html, 1998.
[8] Daniel Savarese Bruce Fryxell Kevin Olson Donald J. Becker,
Thomas Sterling. Communication overhead for space science
applications on the beowulf parallel workstation. High Per-
formance and Distributed Computing , 1995.
[9] Daniel Savarese John E. Dorband Udaya A. Ranawak Charles
V. Packer Donald J. Becker, Thomas Sterling. Beowulf: A
parallel workstation for scientific computation. International
Conference on Parallel Processing , 1995.
[10] Luis Orlando Emerich dos Santos, Paulo Cesar Philippi, and
M C.Damiani. A boolean lattice gas method for predicting
intrinsic permeability of porous medias. Puerto Iguazu, May
[11] Al Geist, Adam Beguelin, and Jack Dongarra. PVM: Parallel
Virtual Machine. MIT Press, 1994.
[12] Cameron Hughs and Tracey Hughes. Object Oriented Mul-
tithreading using C++: architectures and components , vo-
lume 1. John Wiley Sons, 2 edition, 1997.
[13] Guilherme Wunsch Manika. Super-Computador a Preço de
Banana , volume 2. Revista do Linux, 1999.
[14] Brian Masney. Introdutcion to multi-thread programming. Li-
nux Journal, april 1999.
[15] Peter Pacheco. Parallel Programming With MPI. Morgan
Kaufmann Publishers, 1996.
[16] LinuxThreads Programming. Matteo dell omodarme.
[17] Jacek Radajewski and Douglas Eadline. Beowulf HOWTO.
http://www.sci.usq.edu.au/staff/jacek/beowulf/BDP, 1998.
C Apêndice C - Roteiro para paraleliza-
ção e otimização de algoritmos
Apresenta-se a seguir um roteiro básico para paralelização e oti-
mização de programas.
- Identificação de erros lógicos nos algoritmos que impliquem
em processamento desnecessário.
- Avaliação geral da performance do software (com uso de um
profiler^8 ). Avaliação das partes do programa em que vale a
pena o processamento paralelo.
- Uso de opções de otimização do compilador (-O1,-O2,-O3).
- Identificação das partes do programa que são concorrentes.
- Implementação dos algoritmos usando threads ou um dos mé-
todos para troca de mensagens (MPI/PVM).
D Apêndice - HOWTO INSTALL MOSIX
No artigo [1], falou-se do Mosix. Apresenta-se aqui, as instru-
ções para instalação do Mosix em sistemas GNU/Linux.
Listing 8: Roteiro para instalação do MOSIX.
HOWTO - COMO INSTALAR O KERNEL COM O MOSIX :
1 - Fazer o download do kernel 2.4.19 do site ftp :// ftp. kernel. org
2 - Mover o arquivo para o diretório / usr / src mv linux -2.4.19. tar. bz2 / usr / src
3 - Descompactar o kernel cd / usr / src tar - xvjf linux -2.4.19. tar. bz
Remover o link antigo e aplicar novo rm linux -2. ln -s linux -2.4.19 linux -2.
4 - Fazer o download da patch do kernel do mosix MOSKRN -1.8.0. tgz tar - xvzf MOSKRN -1.8.0. tgz mv MOSKRN -1.8.0/ MOSKRN -1.8.0/ patches .2.4.19 / usr / src / linux -2.4.
5 - Aplicar a patch cd / usr / src / linux -2.4. cat patches .2.4.19 | patch - p
6 - Executar os passos de compilação do kernel. make mrproper make xconfig ... configura o kernel ... ... salva configuração com nome : kernel -2 -4 -19 - comMOSIX - v ... abre o arquivo Makefile e inclue informacao MOSADB make dep make clean
(^8) Um profiler é um programa utilizado para identificar os gargalos de desempe-
nho de seu programa. Você executa seu programa dentro do profiler e ele fornece uma estatística das funções e seus tempos de processamento.
make modules make modules_install make bzImage
cp / usr / src / linux -2.4/ arch / i386 / boot / bzImage / boot / vmlinuz - versao cp / usr / src / linux -2.4/ System. map / boot / System .map - versao
7 - Inclue o novo kernel no programa de boot emacs / boot / grub / grub. conf
... adiciona informações do novo kernel .. ... salva ..
8 - O Mosix tem um conjunto de pacotes que são usados para gerenciamento do sistema. Faça o download do arquivo rpm destes pacotes ( ou tar. gz ) , e instale os mesmos em sua máquina.
9 - Reinicializa o sistema e testa o novo kernel.