Programação de Alto Desempenho - 2 Prof: Carla Osthoff E-mail: osthoff@lncc.br
3- Modelos de programação paralela Shared Memory/Threads Posix Win32 treads OpenMP Message Passing MPI Data Parallel OpenCL/Cuda Hybrid
Modelos de programação paralela Modelos de programação paralela são formados através de uma abstração de ambas arquiteturas de hardware e software.
Escolha do modelo A escolha do modelo a ser utilizada é normalmente baseada na arquitetura do sistema disponível e na escolha pessoal. Não existe o melhor modelo, mas existem implementações que podem ser implementadas mais facilmente em determinados modelos.
Arquitetura de computadores de memória compartihada.
3.1 Modelo de Programação de Memória Compartilhada As tarefas compartilham um espaço de endereçamento comum, que é lido e escrito de forma assíncrona. Vários mecanismos tais como locks e semáforos podem ser utilizados para controlar o acesso à memória compartilhada.
Modelo de memória compartilhada baseado em Threads Um único processo pode ter múltiplas threads concorrentes em execução. Podemos fazer uma analogia à um programa que possui uma série de subrotinas executando concorrentemente.
Threads
Threads O programa principal (a.out) executa de forma serial, e cria uma série de tarefas (threads) que podem ser escalonadas pelo sistema operacional para serem executadas de forma concorrente. Cada Thread possui seus dados locais e compartilha todos os recursos do programa principal ( a.out ).
Threads Elimina gastos com replicação de recursos de programa para cada thread. Além disso a comunicação entre os threads se beneficia com o acesso a uma memória global.
Threads É necessário a implementar diretivas de sincronização para garantir a coerência da memória. Os threads podem ser criados e eliminados durante a execução da aplicação ( a.out). Normalmente associado à: Arquiteturas de memória compartilhada Sistemas Operacionais.
Implementações de Threads Do ponto de vista do programador, pode ser composta por: biblioteca de sub-rotinas para serem chamadas pelo código fonte(pthreads). conjunto de diretivas de compilador para serem embutidas no código fonte. (OpenMP) O PROGRAMADOR É RESPONSÁVEL POR DETERMINAR O PARALELISMO
Padrão POSIX (Pthreads) Biblioteca; Especificado pelo padrão IEEE POSIX 1003.1c standard (1995). Linguagem C. Paralelismo explícito, o programador necessita ficar atendo aos detalhes. Obs: Microsoft possui implementação própria de threads
Padrão OpenMP: Diretivas de compilador. Implementado pela maioria de vendedores de software e hardware. Versão em FORTRAN ( desde 1997) Versão em C/C++ ( desde 1998) Portável para diversas plataformas incluindo Unix e Windows NT. Fácil implementação.
Arquitetura de computadores de memória distribuída
3.3 - Modelo de Programação de Troca de Mensagem Composto por um conjunto de tarefas que acessam sua própria memória durante a computação. Múltiplas tarefas podem residir em uma mesma máquina física ou em diversas máquinas individuais.
Modelo de Troca de Mensagem A comunicação dos dados é realizada através de troca de mensagens. A transferência dos dados requer operações cooperativas entre os processos. Uma operação de envio necessita de uma operação de recebimento.
Implementações: Biblioteca. O programador é responsável por especificar o paralelismo. Várias bibliotecas foram implementadas desde a década de 80 Em 1992 foi estabelecido um forum para a criação de um padrão, o padrão Message Passing Interface ou MPI.
3.4 - Paralelismo de Dados Focada na execução paralela de um conjunto de dados. O conjunto de dados é formado tipicamente por uma estrutura comum: array,cubo,etc... Um conjunto de tarefas trabalha coletivamente na mesma estrutura de dados, entretanto cada tarefa trabalha em uma determinada partição da estrutura. As tarefas executam a mesma operação na sua partição exemplo: "add 4 to every array element".
Paralelismo de dados
Arquitetura Cliente/Servidor
Paralelismo de Dados
Paralelismo de Dados É normalmente realizada através de construtores paralelos: Chamadas à uma sub-rotina de paralelismo de dados de uma biblioteca.(opencl/cuda) Diretivas de compilador (High Performance Fortran).
High Performance Fortran (HPF ) As diretivas de compilador permitem ao programador especificar a distribuição e o alinhamento dos dados. Nas implementações em memória distribuída, usualmente o compilador converte o programa em chamadas do código padrão de MPI para distribuir o dados entre os processos.a troca de mensagens é executada de forma transparente ao usuário.
3.5.1 - Modelo de programação Híbrido Implementação usual é a combinação de modelo de troca de mensagens MPI com modelos de threads (POSIX threads ou OpenMP), em ambiente de redes máquinas SMP. Combinação de paralelismo de dados com troca de mensagens, com a implementação de F90 ou HPF em arquitetura de memória distribuída, onde a troca de mensagem (MPI) é utilizada para transmitir o dado entre as tarefas de forma transparente ao programador.
4 Construção de Programas paralelos O projeto e desenvolvimento de programas paralelos tem sido realizado tipicamente como um processo manual. O programador é responsável por identificar e implementar o paralelismo. Usualmente, o desenvolvimento manual do código é um processo iterativo que gasta muito tempo, é complexo leva a diversos erros de desenvolvimento.
Construção de Programas paralelos Durante muitos anos diversas ferramentas foram desenvolvidas para auxiliar o programador na conversão do código serial em código paralelo. Compiladores e Pré-processadores têm sido utilizados para realizar uma conversão automática do código serial para o código paralelo.
Compilador paralelo Compilação automática: O compilador analisa o código fonte e identifica os pontos de paralelização tais como loops (do,for). A análise identifica inibidores á paralelização e uma avaliação do ganho de desempenho coma paralelização.
Compilador paralelo Compilação direcionada pelo programador: Através de diretivas de compilação ou flags,o programador pode indicar explicitamente ao compilador como paralelizar o código. Pode ser utilizado em conjunto com algum grau de paralelização automática.
Construção de Programas paralelos Caso você esteja trabalhando com um código que foi escrito originalmente de forma serial, e tenha restrição de tempo e de orçamento, a paralelização automática deve ser o melhor caminho. Entretanto existem diversos problemas relacionados com a paralelização automática.
Problemas da paralelização automática Possibilidade de criar resultados incorretos Degradação do desempenho. Menos flexível que a paralelização manual. Limitação à um subconjunto do código(loops). Pode não paralelizar caso a análise identifique inibidores ou o código seja muito complexo. A maioria das ferramentas de automação automática são para Fortran.
Desenvolvimento de Código paralelo. O primeiro passo é identificar o problema que você deseja solucionar em paralelo. Caso você esteja começando com um código serial, você também necessita compreender o código.
Desenvolvimento de Código paralelo. Antes de gastar tempo tentando arranjar uma solução paralela para o seu código, é necessário primeiro determinar se o problema pode ser paralelizável.
Exemplo de código paralelizável Calcule o potencial de energia para centenas de conformações de moléculas independentes. Ao final busque a menor energia de conformação. Cada conformação pode ser determinada deforma independente O cálculo da conformação mínima de energia também é um problema paralelizável.
Exemplo de código não paralelizável Calcule a série de Fibonacci de (1,1,2,3,5,8,13,21,...) através da fórmula: F(k + 2) = F(k + 1) + F(k) Observe que o cálculo de K depende dos valores de K-1 e de K, e não podem ser calculados em paralelo
Identificação de hotspots no programa Identifique onde a maior parte do trabalho é realizada. Em geral os programas científicos e técnicos executam a maior parte do seu trabalho em poucos pedaços. Profilers e ferramenta de análise de desempenho podem ajudar. Você deve se concentrar em otimizar os hotspots e ignorar os outros pontos.
Identificação dos gargalos do problema Existem áreas que são desproporcionalmente lentas, ou geram paradas na parte paralelizável? Por exemplo, E/S é um gargalo que normalmente faz o programa rodar mais devagar. É possível reestruturar o programa ou utilizar um algoritmo diferente de forma a eliminar partes do programa que não são necessárias?
Identificar os Inibidores de Paralelismo A dependência entre os dados é uma classe comum de inibidores de paralelismo ( exp. Fibonacci) Investigue a possibilidade de utilizar outros algoritmos.