Introdução à Programação Paralela com Troca de Mensagens Onofre Trindade Jr LCAD-USP 1 Conteúdo Processamento Paralelo Arquiteturas de Computadores Paralelos Paradigmas de Programação Programando com Troca de Mensagens Conclusões 2 O que é Processamento Paralelo? Execução simultânea (concorrente) de vários programas, em diferentes processadores, visando a solução de um único problema 3 Por que Usar Programação Paralela? Algumas classes de problemas: Grandes demais para máquinas seqüenciais – tempo de execução muito longo Os resultados somente são úteis se obtidos dentro de um limite máximo de tempo 4 Vantagens da Computação Paralela Computação mais rápida Problemas maiores Melhor relação custo/benefício Escalabilidade: o desempenho de um programa melhora se ele for executado em mais processadores Tolerante a falhas 5 Validação dos Resultados fornecidos pela Computação Paralela Resultados obtidos devem ser os mesmos: a cada execução do código paralelo quando comparados com aqueles obtidos na versão seqüencial do programa 6 Por que preciso Programar em Paralelo? Não existem ferramentas de auxílio ao desenvolvimento de programas paralelos que identifiquem automaticamente o paralelismo de aplicações genéricas gerem código eficiente para as mesmas 7 Por que preciso Programar em Paralelo? (II) A programação paralela pode ser dividida em duas etapas Encontrar o paralelismo Explorar o paralelismo 8 Determinando Paralelismo É a parte mais difícil Uma dica: como você faria para distribuir sua aplicação entre vários trabalhadores? A sutileza do que você procura é a razão pela qual o compilador não pode fazer a paralelização por você! Código seqüencial de base x código originalmente paralelo Novos algoritmos? 9 Explorando Paralelismo Para explorar o paralelismo, deve-se distribuir a carga computacional entre os diferentes processadores A melhor forma de se fazer isso depende da natureza da aplicação e da arquitetura do computador paralelo usado: mapeamento => eficiência 10 Comunicação entre Processos Geralmente os processos necessitam trocar informações entre si Forma da comunicação dependente da arquitetura do computador: Variáveis Compartilhadas em máquinas com memória compartilhada (shared memory) Troca de Mensagens (message passing) em máquinas com memória distribuída 11 Arquitetura de Computadores Paralelos Existem muitas arquiteturas diferentes Autores agrupam-nas em classes (taxonomia) Taxonomia de Flynn é uma das mais usadas 12 Taxonomia de Flynn SISD: Single Instruction / Single Data. Computadores seqüenciais. MISD: Multiple Instructions / Single Data. Computadores que operam como um pipeline. SIMD: Single Instruction/Multiple Data. Supercomputadores vetoriais. MIMD: Multiple Instructions/Multiple Data. Computadores paralelos intrínsecos. 13 Máquinas MIMD Multiprocessadores com memória compartilhada Multicomputadores com memória distribuída Diferenças: compartilhamento da memória mecanismos utilizados para a comunicação entre processadores 14 Multiprocessadores Fluxo de Instruções UCn EPn ... EP1 ... UC1 FD Memória Compartilhada Globalmente I/O Nó de Processamento 15 Multicomputadores I/O Computador 1 Computador 2 Computador 3 Computador 4 I/O Nó de Processamento 16 Forma de um Programa Paralelo Inicialização Divisão das Tarefas Tarefa 2 Tarefa 1 Tarefa 3 Coleta Fim 17 Controle Explícito do Paralelismo O programador decompõe o problema em tarefas independentes: Decomposição de dados Decomposição de controle O programador codifica explicitamente o controle entre os processos As decomposições podem se misturar em uma aplicação 18 Decomposição de Dados Os dados do problema são particionados entre os diferentes processadores Cada processador executa basicamente o mesmo código, só que sobre dados diferentes 19 Exemplos de Decomposição de Dados Solução numérica de equações diferenciais parciais pelo método das diferenças finitas Troca de informações nas fronteiras 20 Exemplos de Decomposição de Dados (II) Cálculo da área sob uma curva Tarefas independentes! 21 Vantagens da Decomposição de Dados Pode-se dividir o domínio de forma a que todos os processadores realizem a mesma quantidade de computação: balanço de carga Muitos problemas exigem comunicação entre as tarefas somente nas fronteiras dos subdomínios de dados Muitos problemas de Física e Engenharia se adaptam à Decomposição de Dados 22 Decomposição de Controle Divisão das tarefas baseada nas funções a serem executadas Útil quando não se conhece, a priori, o volume de computação total – pode facilitar o balanceamento de carga 23 Exemplo de Decomposição de Controle Estrutura tipo pipeline 1 2 3 5 4 Cada processador cuida de uma única etapa do processo 24 Problemas com a Decomposição de Controle Não é de tão fácil aplicação quanto à decomposição de dados É mais difícil de implementar: exige maior coordenação entre os processos A adição de mais processadores não é simples 25 Níveis de Particionamento de um Programa Granularidade: quantidade de computação entre sincronizações Dividida entre Fina Média Grossa Execução do programa envolve combinação desses níveis 26 Níveis de Particionamento de um Programa (II) Níveis de granularidade +Comunicação +Sincronismo Programas +Paralelismo Subprogramas Subrotinas Loops Instruções Grossa Média Fina 27 Níveis de Particionamento de um Programa (III) Instruções: compilador Loops: compilador e programador Subrotinas, subprogramas: programador Programas: SO 28 Sincronismo e Comunicação Processos devem cooperar entre si Troca de dados deve ser feita na ordem (seqüência) correta Sincronismo é necessário! 29 Medindo o Desempenho do Programa Paralelo Quando se desenvolve uma aplicação paralela, é útil sabermos o quanto seu desempenho se aproxima do ótimo Essa valor teórico é função: da fração seqüencial f do código do nº de processadores, n 30 Medindo o Desempenho do Programa Paralelo (II) Speedup (S): Quantas vezes o código paralelo fica mais rápido (que sua versão seqüencial) com o nº de processadores utilizados Lei de Amdahl: 1 S (1 f ) f n 31 Medindo o Desempenho do Programa Paralelo (III) 32 Medindo o Desempenho do Programa Paralelo (IV) A diferença entre o valor “ideal” e o valor obtido na prática aumenta com o aumento do nº de processadores Para todo programa paralelo, há uma valor de n acima do qual não compensa ir 1 n , S f 33 Medindo o Desempenho do Programa Paralelo (V) No mundo real, o overhead causado pela comunicação entre processadores chega até a reduzir o speedup após certos valores de n Menos de 5% de código seqüencial é difícil de se conseguir! 34 Medindo o Desempenho do Programa Paralelo (VI) Desempenho (D): Mede a “taxa de uso” dos processadores É relacionada com o Speedup através da relação: S D 100 % n 35 Medindo o Desempenho do Programa Paralelo (VII) 36 Medindo o Desempenho do Programa Paralelo (VIII) Quanto maior o desempenho, maior é a participação dos processadores na resolução do problema 37 Programando com Troca de Mensagens (TM) Ferramentas para Programação Paralela Compiladores paralelizadores (Cray, etc) Linguagens paralelas (HPF, Occam, C*, etc) Bibliotecas de troca de mensagens (PVM, MPI, Parmacs, etc) Depuradores / analisadores de código (XPVM, Pablo, Paragraph, etc) Ambientes de desenvolvimento (Forge, etc) 38 Características da TM Criação de processos em processadores diferentes Encerramento desses processos Transferência de dados (na forma de mensagens) entre esses processos 39 Sistemas de TM Se apresentam normalmente na forma de bibliotecas Proprietárias e de Terceiros Proprietárias: fornecidas pelo fabricante do computador Mais rápidas Mais adaptadas à arquitetura 40 Sistema de TM (II) Terceiros: geralmente executam em diferentes arquiteturas Portabilidade das aplicações Execução em plataformas heterogêneas PVM e MPI são exemplos mais comuns para FORTRAN e C Disponíveis para máquinas UNIX e Windows. 41 Tipos de Comunicação em TM Em ambientes de TM, cada processo pode: Enviar uma mensagem para outro processo Enviar a mesma mensagem para vários outros processos simultaneamente (broadcast) Receber mensagens enviadas para ele 42 Tipos de Comunicação em TM (II) Cada forma de comunicação é normalmente executada através de uma chamada de subrotina O sistema de TM cuida dos detalhes de transmissão e recepção dos dados no computador 43 Tipos de Comunicação em TM (III) O programador deve projetar a aplicação paralela Como uma coleção de tarefas A lógica e o fluxo de execução são normalmente controladas pela comunicação entre os processos 44 Tipos de Comunicação em TM (IV) O envio/recepção podem ser bloqueantes: a rotina não retorna até completar a transmissão/recepção não-bloqueantes: a rotina retorna antes de completar a transmissão/recepção 45 Tipos de Comunicação em TM (V) O envio/recepção podem ser síncronos: existe um instante no tempo onde transmissor e receptor estão simultaneamente comprometidos com o processo de transferência de dados 46 Tipos de Comunicação em TM (VI) Modos bloqueantes devem ser evitados, pois os processos poderiam estar fazendo computação útil durante a comunicação 47 Tipos de Comunicação em TM (VII) O ideal é que se misture computação com troca de mensagens: Envios não-bloqueantes Recepções não-bloqueantes Se todas as tarefas tentarem se comunicar ao mesmo tempo, pode haver contenção na linha de comunicação! 48 Divisões de Tarefa Sistemas de TM são usados para implementar as formas de divisão de tarefas mais comuns: Pipeline Paralelismo de Dados Mestre-Escravo 49 Planejamento do Sistema Escolhido o modelo, a lógica da aplicação fica determinada Essa lógica é implementada com a ajuda da biblioteca de TM O programador precisa Determinar que dado é usado por qual processo e em que ordem Implementar a comunicação entre os processos invocando as rotinas da biblioteca de TM Escrever as tarefas que lerão os dados e executarão o trabalho 50 Desenvolvimento de um Código TM a Partir de um Código Seqüencial As regras abaixo são úteis no desenvolvimento de aplicações com TM 1) Comece com uma versão seqüencial do programa que Não tenha código não executado Construções obsoletas 51 Desenvolvimento de um Código TM ... (II) 2) Verifique as opções de compilação disponíveis, principalmente aquelas que monitoram o código em tempo de execução estouro de limites em vetores problemas nos valores de ponto flutuante minimize as otimizações 52 Desenvolvimento de um Código TM ... (III) 3) Crie vários conjuntos de entradas/saídas do código seqüencial para comparação com o resultado do código paralelo 4) Faça uma análise do código serial (profiling), ajustando-o para que tenha um bom desempenho 53 Desenvolvimento de um Código TM ... (IV) 5) Tente extrair o paralelismo da aplicação. Descubra os trechos de código que possam (e justifiquem) ser paralelizados Se em mais de um trecho, comece pelo de mais alto nível (maior granularidade) Use o profiling como guia! 54 Desenvolvimento de um Código TM... (V) 7) Determine o uso das variáveis e dos vetores utilizados: a) Lidos ou modificados (L/M) somente na parte seqüencial b) L/M somente na parte paralela c) L/M localmente a cada tarefa independente d) L/M por várias tarefas independentes e) L/M pela partes seqüencial e paralela f) M na parte seqüencial, L na parte paralela g) M na parte paralela, L na parte seqüencial A e C Ok!, os outros casos precisam de tratamento especial 55 Desenvolvimento de um Código TM... (VI) 8) Escolha o paradigma apropriado 9) Implemente uma versão inicial: Funcionalmente correta (esqueça o desempenho!) Seja conservador no uso de sincronismo Particione usando poucos processadores Insira mensagens em locais apropriados para depurar o código 56 Desenvolvimento de um Código TM... (VII) 10) Expanda os testes Faça pequenas alterações acompanhadas de testes (chato, mas funciona!) Cuidado com print, printf: podem alterar o funcionamento do código por alterar o sincronismo Teste cada caso gerado anteriormente em vários nós 57 Desenvolvimento de um Código TM... (VIII) Agora pode-se pensar em melhorar o desempenho... 11) Remova todos as operações de I/O desnecessárias Elas podem mascarar problemas de sincronismo Reduzem desempenho (I/O de vídeo) 12) Melhore a comunicação Elimine mensagens desnecessárias Agrupe mensagens correlatas Tente sobrepor comunicação com computação quando possível 58 Exemplo de Paralelização Aplicação ao cálculo da área sob uma curva no intervalo [a,b] O método mais direto de paralelização é o y f ( x) paradigma de decomposição de dados: dividir o intervalo [a,b] em n subintervalos iguais Regra do trapézio 59 Visão de alto nível Inicialização Divisão do Intervalo [a+h,a+2h] [a,a+h] [a+2h,a+3h] Soma dos resultados Impressão 60 Divisão do Intervalo Cada processador recebe um subintervalo de comprimento (b a ) h n onde n é o nº de processadores usados h 61 Divisão de Trabalho Define-se um processo mestre para coordenar o processo Esse processo mestre irá disparar os n-1 (2) processos auxiliares do j=2,3 create(“quadr”, tid(j)) enddo tid(1) é o identificador do mestre! 62 Dados enviados pelo Mestre Cada tarefa precisa saber: os extremos do seu subintervalo o valor de h Processo mestre manda esses dados para todas as tarefas: if (me.eq.1) then do j=2,3 send (a+(j-1)h,(a+j)h) to tid(j) send (h) to tid(j) enddo endif 63 Recepção pelos Filhos Cada processo filho recebe esses dados: if (me.ne.1) then rec (a_loc, b_loc) from tid(1) rec (h) from tid(1) endif 64 Transmissão/Recepção Combinadas Pode-se agrupar tudo em um mesmo trecho de código! (SPMD) if (me.eq.1) then do j=2,3 send (a+(j-1)h,(a+j)h) to tid(j) send (h) to tid(j) enddo else rec (a_loc, b_loc) from tid(1) rec (h) from tid(1) endif 65 Cada Tarefa calcula a área do seu subintervalo Cada processo filho calcula a área pela regra do Trapézio: f (a _ loc) f (b _ loc) I parcial h 2 onde: h b _ loc a _ loc Uma vez calculado, cada filho o manda seu Iparcial para o mestre 66 Mestre recebe áreas parciais if (me.ne.1) then send (i_parcial) to tid(1) else i_total=i_parcial do j=2,3 rec (i_parcial) from tid(j) i_total=i_total+i_parcial enddo endif 67 Mestre recebe áreas parciais Mestre mata os processos filhos: if (me.eq.1) then do j=2,3 call kill(tid(j)) enddo endif 68 Conclusões Computação paralela é a forma mais acessível de se resolver problemas que exigem muita computação Está se difundindo cada vez mais mais pela queda no custo dos componentes eletrônicos 69 Conclusões As bibliotecas de comunicação PVM e MPI utilizadas em multicomputadores constiuem o ambiente mais básico e acessível para a prática de processamento paralelo. 70