UESC UNIVERSIDADE ESTADUAL DE SANTA CRUZ PRÓ-REITORIA DE PESQUISA E PÓS-GRADUAÇÃO - PDF
UESC UNIVERSIDADE ESTADUAL DE SANTA CRUZ PRÓ-REITORIA DE PESQUISA E PÓS-GRADUAÇÃO
Download "UESC UNIVERSIDADE ESTADUAL DE SANTA CRUZ PRÓ-REITORIA DE PESQUISA E PÓS-GRADUAÇÃO"
Iasmin Raminhos Cabral
1 UESC UNIVERSIDADE ESTADUAL DE SANTA CRUZ PRÓ-REITORIA DE PESQUISA E PÓS-GRADUAÇÃO Programa de Pós-Graduação em Ciência, Inovação e Modelagem em Materiais PROCIMM ELIZABETH BRITO LLAMOSAS GOMES PARALELIZAÇÃO DO CÓDIGO PIC-MCC PARA APLICAÇÕES TECNOLÓGICAS DE PLASMAS ILHÉUS BAHIA 2012
2 ELIZABETH BRITO LLAMOSAS GOMES PARALELIZAÇÃO DO CÓDIGO PIC-MCC PARA APLICAÇÕES TECNOLÓGICAS DE PLASMAS Dissertação apresentada ao Mestrado de Ciência, Inovação e Modelagem em Materiais, para obtenção do título de Mestre em Engenharia de Materiais. Orientador: Prof. Dr. Gesil Sampaio Amarante Segundo. ILHÉUS BAHIA 2012 ii
3 G393 Gomes, Elizabeth Brito Llamosas. Paralelização do código PIC-MCC para aplicações tecnológicas de plasmas / Elizabeth Brito Llamosas Gomes. Ilhéus : UESC, xvi, 117f. : il. Orientador : Gesil Sampaio Amarante Segundo. Dissertação (mestrado) Universidade Estadual de Santa Cruz. Programa de Pós-graduação em Ciência, Inovação e Modelagem em Materiais. Inclui bibliografia. 1.Engenharia de materiais. 2. Filmes finos. 3. Engenharia do plasma. 4. Programação paralela (computação). I. Segundo, Gesil Sampaio Amarante. II. Título CDD iii
4 ELIZABETH BRITO LLAMOSAS GOMES PARALELIZAÇÃO DO CÓDIGO PIC-MCC PARA APLICAÇÕES TECNOLÓGICAS DE PLASMAS DISSERTAÇÃO SUBMETIDA AO CORPO DOCENTE DO PROGRAMA DE PÓSGRADUAÇÃO EM CIÊNCIA, INOVAÇÃO E MODELAGEM EM MATERIAIS DA UNIVERSIDADE ESTADUAL DE SANTA CRUZ COMO PARTE DOS REQUISITOS NECESSÁRIOS PARA A OBTENÇÃO DO GRAU DE MESTRE EM CIÊNCIA, INOVAÇÃO E MODELAGEM EM MATERIAIS. Ilhéus-BA, 02/05/2012. Aprovada por: Prof. Dr. Gesil Sampaio Amarante Segundo (UESC) Prof. Dr. Esbel Tomás Valero Orellana (UESC) Profa. Dra. Marisa Roberto (ITA) iv
5 DEDICATÓRIA Dedico este trabalho a seis pessoas de grande importância em minha vida, a meu querido pai Alvaro Llamosas Collado, minha carinhosa mãe Lízia Maria Brito Llamosas, meu amado esposo Marcio Oliveira Gomes e aos meus maravilhosos filhos Felipe Llamosas Gomes, Michele Llamosas Gomes e Bruno Gabriel Gomes. v
6 AGRADECIMENTOS: Em primeiro lugar agradeço a Deus pela vida, pelo amor, pela sua infinita misericórdia em me agraciar e oportunizar a concretização de um sonho, um ideal a muito desejado e hoje conquistado. Ao meu orientador prof. Dr. Gesil Sampaio Amarante Segundo, por toda a dedicação, apoio, paciência, disposição e orientação durante este trabalho. Por ter sido mais que um orientador, foi acima de tudo amigo, que com seu brilhantismo e humildade me ensinou a olhar além, a buscar no horizonte a perspectiva do sucesso, da conquista, do realizar. Ao grupo de pesquisadores de Berkeley, que desenvolveram o código XPDP1 e o disponibilizaram livremente para estudos. À querida amiga Lília Marta Brandão Soussa Modesto, por ter me ajudado no início, pelo seu incentivo e apoio. À professora Dra. Martha Ximena Torres Delgado, pela disponibilização de seu tempo em me ensinar MPI. À Eduardo Almeida Costa (Duca), por ter dado todo o suporte com o Linux e com o cluster. Ao prof. Dr. Esbel Tomás Valero Orellana, pelo seu apoio e por suas aulas de OpenMP. Ao prof. Dr. Dany Sanchez Dominguez, por sua dedicação na ministração das aulas no mestrado, e por sua paciência em corrigir meu trabalho. Ao prof. Dr. Ari Melo Mariano, por sua pronta disponibilidade em me ajudar com a pesquisa de meta análise. À Jaqueline Vieira Barreto, pela compreensão, pelo apoio, por suas informações, e pelas conversas sempre muito proveitosas que tivemos sobre a dissertação. Ao meu marido, meus pais e a meus filhos pelo estímulo, carinho e compreensão que foram imprescindíveis para conclusão de mais este percurso. vi
7 O temor do Senhor é o princípio da sabedoria. (Prov.1:7) vii
8 PARALELIZAÇÃO DO CÓDIGO PIC-MCC PARA APLICAÇÕES TECNOLÓGICAS DE PLASMAS RESUMO Neste trabalho de dissertação, é apresentada a avaliação de desempenho de um código computacional paralelizado que simula um plasma contido entre dois eletrodos, e acompanha a cada pequeno intervalo de tempo, os movimentos de cada partícula deste plasma, enquanto estas são influenciadas por campos eletromagnéticos internos auto-consistentes e/ou por campos externos. Este código é chamado XPDP1 (X Plasma Device Planar 1-Dimensional), foi desenvolvido na linguagem C, utiliza o método PIC (Particle In Cell) acoplado ao Método de Colisões de Monte Carlo (MCC), e utiliza gases puros, como argônio, oxigênio e outros. A parte gráfica do XPDP1 foi retirada, e a seguir, ele foi paralelizado utilizando-se dois paradigmas de programação paralela: a memória compartilhada empregando-se o Padrão OpenMP e a troca de mensagens com o Padrão MPI. Um cluster homogêneo foi o ambiente em que os testes de execução dos programas foram realizados. Um microcomputador com processador i7-930 também foi utilizado para a realização de medidas preliminares de desempenho, bem como um notebook com processador i7-2630qm. Para quantificar o desempenho da execução paralela em cada arquitetura, foram realizados as medições dos tempos de execução e os cálculos de speedups (aceleração paralela) e eficiência. Os resultados obtidos mostraram que foi possível obter acelerações da ordem de até 10 vezes utilizando 32 núcleos no cluster CACAU, o que permite o uso deste código em problemas hoje inviáveis com a versão serial. Palavras-chave: códigos PIC/MCC; programação paralela; plasma frio. viii
9 PARALLELIZATION OF PIC-MCC CODE FOR TECHNOLOGY APPLICATIONS OF PLASMAS ABSTRACT In this dissertation work, it s presented the performance evaluation of a parallelized computational code that simulates a plasma contained between two electrodes, and accompanies the movements of each particle of the plasma each small time interval, while they are influenced by internal (self-consistent) and/or external electromagnetic fields. This code is called XPDP1 (X Plasma Device Planar 1-Dimensional). It was developed in C language, uses the PIC (particle in cell) method coupled with Monte Carlo Collisions (MCC), method and it uses pure gases such as argon, oxygen and others. The XPDP1 graphical part was removed, and then he was parallelized using two parallel programming paradigms: the shared memory using the OpenMP standard and the exchange of messages with the MPI standard. A homogeneous cluster was the environment in which the tests of programs execution have been conducted. A microcomputer with i7-930 processor was also used to the accomplishment of preliminary performance measurements, as well as a notebook with i7-2630qm processor. To quantify the performance of parallel execution in each architecture measurements of execution times and calculations of speedup and efficiency were performed. The results showed that it was possible to obtain accelerations up to approximately 10 times using 32 nodes, which allows the use of this code on problems now unfeasible for the serial version. Keywords: PIC/MCC codes; parallel programming; cold plasma. ix
10 LISTA DE FIGURAS FIGURA 1 Os quatro estados da matéria....2 FIGURA 2 Esquema do processador Intel i FIGURA 3 Esquema do processador Intel Xeon FIGURA 4 Esquema do processador Intel i7-2630qm....6 FIGURA 5 Quantidade de publicações sobre códigos PIC por ano....7 FIGURA 6 Quantidade de citações sobre códigos PIC por ano....7 FIGURA 7 Micrografias de filmes finos de ZrN depositados sobre um substrato de Si....9 FIGURA 8 Lâmpada de plasma FIGURA 9 Esquema de um processo de deposição por sputtering de campo estático (DC).. 14 FIGURA 10 Magnetron sputtering elétrons confinados próximos à superfície do alvo pelo campo magnético dos ímãs FIGURA 11 Eventos que ocorrem na superfície que é bombardeada com partículas energéticas de tamanho atômico FIGURA 12 Partição das etapas na computação serial FIGURA 13 Partição das etapas na computação paralela FIGURA 14 Classificação de Flynn FIGURA 15 Classificação de Flynn-Johnson FIGURA 16 Esquema de arquiteturas (a) multiprocessador; (b) multicomputador; (c) vetorial; (d) multicore; (e) cluster FIGURA 17 Esquema de arquitetura grid FIGURA 18 Memória Distribuída FIGURA 19 Memória Compartilhada (a) UMA (b) NUMA FIGURA 20 Modelo de programação OpenMP FIGURA 21 Classificação dos modelos de simulação computacional para plasma FIGURA 22 Esquema de uma simulação cinética via partículas FIGURA 23 Esquema de um ciclo do método PIC/MCC FIGURA 24 Esquema do método leapfrog FIGURA 25 Grade numérica onde as super-partículas ( ) interagem entre si através de campos elétricos e campos magnéticos (símbolos e Δ) FIGURA 26 Decomposição de domínio em regiões espaciais (a) e decomposição de domínio pelo índice das partículas (b) FIGURA 27 Esquema de um circuito RLC em série e fonte de voltagem/corrente, para o modelo unidimensional XPDP1, onde considera-se o movimento das partículas na direção x. 57 FIGURA 28 Janelas de execução do XGrafix/XPDP1. (a) Painel de Controle; (b) Lista de janelas de diagnóstico que podem ser visualizadas; (c) e (d) exemplos de diagnósticos FIGURA 29 Fluxo simplificado de execução do XPDP1 com o XGrafix habilitado (1 ciclo) FIGURA 30 Fluxo simplificado de execução do XPDP1 com o XGrafix desabilitado (1 ciclo). 60 FIGURA 31 Grade numérica FIGURA 32 Tempo total de execução para ciclos do XPDP1 original, no i x
11 FIGURA 33 Tempo de execução para ciclos das funções do XPDP1 com o XGrafix desabilitado, no i FIGURA 34 Tempo de execução para ciclos do XPDP1 alterado sem o XGrafix, no i FIGURA 35 Distribuição das partículas entre as threads, e junção na thread mestre FIGURA 36 parallel for vazio FIGURA 37 parallel for com a diretiva de sincronização atomic FIGURA 38 parallel for com a diretiva de sincronização critical FIGURA 39 parallel for com a diretiva de sincronização flush FIGURA 40 Decomposição de domínio das partículas para 4 processos e vetor de densidade N(x) FIGURA 41 Esquema de um ciclo do método PIC/MCC paralelizado com balanceamento de carga FIGURA 42 Esquema de paralelização de MPI com OpenMP FIGURA 43 Tempo de execução para iterações do XPDP1 sem o XGrafix, paralelizado com OpenMP e executado com 1 thread, no i FIGURA 44 Tempo de execução para iterações do XPDP1 sem o XGrafix, paralelizado com OpenMP e executado com 1 thread, no CACAU FIGURA 45 Comparação dos tempos de execução das 3 versões do XPDP1, para ciclos, no desktop Core i FIGURA 46 Tempo de execução para iterações do XPDP1 sem o XGrafix, função exp_move paralelizada com OpenMP, com partículas iniciais, no Core i FIGURA 47 Tempo de execução para iterações do XPDP1 sem o XGrafix, função exp_move paralelizada com OpenMP, com partículas iniciais, no Core i FIGURA 48 Tempo de execução para iterações do XPDP1 sem o XGrafix, função exp_move paralelizada com OpenMP, com partículas iniciais, no Core i FIGURA 49 Tempo de execução para iterações do XPDP1 sem o XGrafix, função exp_move paralelizada com OpenMP, com partículas iniciais, no cluster CACAU FIGURA 50 Tempo de execução para iterações do XPDP1 sem o XGrafix, função exp_move paralelizada com OpenMP, com partículas iniciais, no CACAU FIGURA 51 Tempo de execução para iterações do XPDP1 sem o XGrafix, função exp_move paralelizada com OpenMP, com partículas iniciais, no CACAU FIGURA 52 Speedup da função exp_move paralelizada, no Core i FIGURA 53 Eficiência da função exp_move paralelizada, no Core i FIGURA 54 Tempo de execução total do XPDP1 paralelizado sem XGrafix, no Core i7-930, para ciclos FIGURA 55 Tempo de execução total do XPDP1 paralelizado sem XGrafix, no CACAU FIGURA 56 Evolução no número de partículas no plasma no decorrer da execução do XPDP1 paralelizado, no Core i7-930, com partículas iniciais xi
12 FIGURA 57 Evolução no número de partículas no plasma no decorrer da execução do XPDP1 paralelizado, no Core i7-930, com partículas iniciais FIGURA 58 Evolução no número de partículas no plasma no decorrer da execução do XPDP1 paralelizado, no Core i7-930, com partículas iniciais FIGURA 59 Tempo de execução do XPDP1 com as funções exp_move e gather paralelizadas, no Core i FIGURA 60 Perda não-física de partículas no decorrer da execução do XPDP1 com a função gather paralelizada, no Core i7-930, com partículas iniciais FIGURA 61 Vetor das posições e grade numérica FIGURA 62 Tempo de execução para iterações da função gather paralelizada com OpenMP, com partículas iniciais, no Core i FIGURA 63 Tempo de execução para iterações da função gather paralelizada com OpenMP, com partículas iniciais, no Core i FIGURA 64 Tempo de execução para iterações da função gather paralelizada com OpenMP, com partículas iniciais, no Core i FIGURA 65 Tempo de execução para ciclos do XPDP1 paralelizado com MPI, com partículas iniciais, gás Argônio, no cluster CACAU FIGURA 66 Tempo de execução para ciclos do XPDP1 paralelizado com MPI, com partículas iniciais, gás Argônio, no cluster CACAU FIGURA 67 Speedup (a) e Eficiência (b) para ciclos do XPDP1 paralelizado com MPI, com 40 mil e 20 mil partículas iniciais, gás Argônio, sem balanceamento de carga, no cluster CACAU FIGURA 68 Tempo de execução em relação à quantidade de vezes que é realizado o balanceamento de carga, para ciclos do XPDP1 paralelizado com MPI, com 40 mil partículas iniciais, gás Argônio, no cluster CACAU FIGURA 69 Tempo de execução para ciclos do XPDP1 paralelizado com MPI, com partículas iniciais, no cluster CACAU, utilizando o gás Oxigênio FIGURA 70 Tempo de execução para ciclos do XPDP1 paralelizado com MPI, com partículas iniciais, no cluster CACAU, utilizando o gás Oxigênio FIGURA 71 Speedup (a) e eficiência (b) para ciclos do XPDP1 paralelizado com MPI, com e partículas iniciais, no cluster CACAU, utilizando o gás Oxigênio FIGURA 72 Tempo de execução para ciclos do XPDP1 paralelizado com MPI, com partículas iniciais, no cluster CACAU, utilizando o gás Oxigênio FIGURA 73 Speedup (a) e eficiência (b) para ciclos do XPDP1 paralelizado com MPI, com partículas iniciais, no cluster CACAU, utilizando o gás Oxigênio FIGURA 74 Tempo de execução para ciclos do XPDP1 paralelizado com MPI, com partículas iniciais, no cluster CACAU, utilizando o gás Oxigênio FIGURA 75 Speedup (a) e eficiência (b) para ciclos do XPDP1 paralelizado com MPI, com partículas iniciais por espécie, no cluster CACAU, utilizando o gás Oxigênio xii
13 FIGURA 76 Tempo de execução para ciclos do XPDP1 paralelizado versão híbrida, com partículas iniciais, no cluster CACAU, utilizando o gás Oxigênio FIGURA 77 Speedup para ciclos do XPDP1 paralelizado versão híbrida, com partículas iniciais, no cluster CACAU, utilizando o gás Oxigênio, com balanceamento de carga xiii
14 LISTA DE TABELAS E QUADROS TABELA 1 Publicações mais citadas sobre códigos PIC....7 TABELA 2 Medida do overhead do parallel for vazio TABELA 3 Medida do overhead das diretivas de sincronização, no i TABELA 4 Função exp_move paralelizada executada com iterações, no Core i TABELA 5 Função exp_move paralelizada executada com iterações, no CACAU TABELA 6 Speedup do XPDP1 com as funções exp_move e gather paralelizadas, no Core i TABELA 7 Eficiência do XPDP1 com as funções exp_move e gather paralelizadas, no Core i TABELA 8 Speedup do XPDP1 paralelizado com OpenMP, para ciclos TABELA 9 Speedup do XPDP1 paralelizado com MPI, no cluster CACAU TABELA 10 Tempo de execução da versão híbrida para ciclos, no CACAU QUADRO 1 Elementos da interface OpenMP QUADRO 2 Classificação do speedup QUADRO 3 Classificação da Eficiência QUADRO 4 Arquivos fontes do XPDP1 e suas funções xiv
15 SUMÁRIO RESUMO... VIII ABSTRACT... IX INTRODUÇÃO... 1 CAPÍTULO 1 FILMES FINOS Processos de Deposição Deposição assistida por plasma Sputtering CAPÍTULO 2 COMPUTAÇÃO PARALELA Arquiteturas Paradigmas Memória Compartilhada OpenMP Memória Distribuída MPI Métricas de Desempenho Avaliação de Desempenho CAPÍTULO 3 CÓDIGOS DE SIMULAÇÃO COMPUTACIONAL CINÉTICA DE PARTÍCULAS Abordagens para paralelização de códigos PIC O código eletrostático unidimensional XPDP Análise do funcionamento do sistema CAPÍTULO 4 PARALELIZAÇÃO DO CÓDIGO XPDP Estratégia de paralelização do código Paralelização do código com OpenMP Paralelização do código com MPI Paralelização do código com MPI e OpenMP (híbrida) CAPÍTULO 5 RESULTADOS E DISCUSSÕES Resultados da versão paralelizada com OpenMP Resultados da versão paralelizada com MPI Resultados da versão híbrida, paralelizada com MPI e OpenMP CONCLUSÕES E TRABALHOS FUTUROS ANEXO A ANEXO B xv
16 ANEXO C ANEXO D ANEXO E ANEXO F ANEXO G ANEXO H REFERÊNCIAS BIBLIOGRÁFICAS xvi
17 INTRODUÇÃO O homem vem desenvolvendo e aprimorando materiais desde seus primórdios na Terra. Inicialmente, usava instrumentos e ferramentas feitos a partir de pedaços de ossos, madeira e pedras. Posteriormente, com o domínio do fogo, ele desenvolveu ferramentas de metal. Com a revolução industrial e a invenção das máquinas a vapor houve uma grande evolução tecnológica. Contudo, devido ao desgaste dos materiais que constituem o motor destas máquinas e de tantas outras, ocasionado por altas temperaturas e altas pressões e devido também ao desgaste mecânico das partes móveis das máquinas, o homem sentiu a necessidade de melhorar as propriedades destes materiais, tais como, resistência a corrosão, dureza elevada, baixo coeficiente de atrito, estabilidade térmica e química. Então, ele desenvolveu novas técnicas de tratamento de superfícies. Entre elas, é cada vez mais importante citar a deposição de filmes finos assistida a plasma. Plasma é uma palavra grega e designa um material moldável ou que flui. Atualmente o plasma é mais conhecido como o 4º estado da matéria, isto é, um fluido composto de partículas gasosas, íons e elétrons livres em constante interação, conforme mostrado na FIGURA 1. Estima-se que 99% da matéria do Universo exista sob a forma de plasma. Por exemplo: estrelas, vento solar, auroras Austral e Boreal, chamas do fogo. Assim como os gases, o plasma não possui forma ou volume 1
18 definidos, a não ser quando contido em um recipiente, e, sob a influência de um campo magnético, pode formar estruturas como filamentos, raios e camadas. O plasma é descrito como um meio eletricamente neutro de partículas positivas e negativas, isto é, a carga total de um plasma é aproximadamente zero. Essas partículas não são "livres", quando as cargas se movem, elas geram correntes elétricas com campos magnéticos e, como resultado, cada uma é afetada pelos campos das outras. FIGURA 1 Os quatro estados da matéria. Fonte: Adaptada de Os plasmas despertam grande interesse porque podem ser utilizados em diversas aplicações, tais como, deposição de filmes finos, tratamento de efluentes, maçaricos de plasma para cortes, tochas de plasma, processamento de micro-chips, e outras. Para estudar o plasma e seu comportamento, contamos com modelos teóricos e empíricos bem estabelecidos para uma grande variedade de situações, mas muitas vezes é vantajoso utilizarmos de simulações computacionais. Os resultados obtidos de uma simulação podem ser usados para complementar a análise de estudos observacionais, utilizando modelos conceituais e a teoria analítica. Neste trabalho, foi utilizada uma simulação computacional de descrição cinética, chamada método de simulação via códigos de partícula na célula (PIC particle in cell), onde são acompanhados, a cada pequeno intervalo de tempo, os movimentos de cada partícula, em uma grade espacial discreta, enquanto são 2
19 influenciados por campos eletromagnéticos internos auto-consistentes e/ou por campos externos. O código computacional utilizado foi o XPDP1 (X Plasma Device Planar 1- Dimensional) (http://langmuir.eecs.berkeley.edu/pub/codes/xpdp1), que é unidimensional, eletrostático e permite simular um plasma contido entre dois eletrodos, que estão conectados através de um circuito externo RLC (resistência/indutância/ capacitância), podendo também ser aplicado um campo magnetostático externo. O XPDP1 implementa o algoritmo que utiliza o método PIC acoplado ao Método de Colisões de Monte Carlo (MCC), e utiliza gases puros, como hélio, argônio, oxigênio e outros, é, portanto, um código PIC-MCC. A versão disponibilizada do XPDP1 para a realização de pesquisas é uma versão serial, e dependendo do tipo de gás utilizado, e das espécies de partículas a serem acompanhadas, sua execução demanda um tempo considerável e, por isso, necessita da computação de alto desempenho para executá-las mais rapidamente, viabilizando estudos mais complexos. Para obter alto desempenho, é preciso explorar o paralelismo, que é o emprego de múltiplas unidades de processamento (chamadas de núcleos) em um único chip ou estruturas que envolvem várias unidades de processamento em redes dedicadas para a divisão do esforço de computacional. Ao longo da história dos computadores, a computação de alto desempenho tem sido utilizada para acelerar a execução de simulações. Ela consiste de vários processadores conectados, trabalhando juntos, executando de forma concomitante, duas ou mais operações de um sistema. Se todas as partes desse sistema, que é serial, e leva T unidades de tempo para ser executado sequencialmente, pudesse ser perfeitamente paralelizado, ele levaria T/p unidades de tempo utilizando-se p processadores. No entanto, vários fatores podem comprometer este ganho em desempenho, entre eles, os que estão cristalizados na lei de Amdahl (CHANDRA et al., 2001; HENNESSY; PATTERSON, 2008). Para se trabalhar com alto desempenho, algumas arquiteturas foram desenvolvidas, como o PVP (Parallel Vector Processors), o SMP (Symmetric 3
20 Multiprocessors), o MPP (Massive Parallel Processors), os clusters, e os grids (TANENBAUM, 2001). Além do hardware, o software também é construído para permitir a divisão de trabalho entre as unidades de processamento, o que costuma ser mais complicado, pois geralmente é necessário que os processadores se comuniquem para atualizar as memórias, regiões de sobreposição de domínio, etc. Então, alguns paradigmas de programação paralela também foram desenvolvidos, tanto para estruturas com memória distribuída como para memória compartilhada. Esta dissertação versa sobre a avaliação de desempenho do código XPDP1 paralelizado de três maneiras, com o Padrão OpenMP (Open MultiProcessors), usado na paralelização para máquinas de memória compartilhada, com o Padrão MPI (Message Passing Interface), biblioteca de paralelização para máquinas de memória distribuída (utilizando o paradigma de troca de mensagens), e uma versão híbrida com ambos os padrões. Foi realizado um estudo detalhado do desempenho de cada versão paralelizada, em um cluster homogêneo, e, diante dos resultados obtidos, foi possível obter acelerações da ordem de até 10 vezes utilizando 32 núcleos, o que permite o uso deste código em problemas hoje inviáveis com a versão serial. O XPDP1 faz parte de uma família de códigos que também contam com versões em 2D e cilíndrica e que podem se beneficiar das mesmas estratégias aplicadas aqui. Tanto para analisar os gargalos de execução do XPDP1, em sua versão serial, como para coletar os dados do programa paralelizado através do OpenMP, foi utilizado um microcomputador com um processador Intel Core i7 modelo 930 (FIGURA 2), de 2.80 GHz com 4 núcleos, capazes de executar 2 threads por núcleo (por possuir Hyper-Threading), memória RAM de 8 GB, memória cache de KB, sob Ubuntu Linux, versão 11.10, 64 bits, kernel Posteriormente, todos os casos foram executados no cluster C.A.C.A.U. (Centro de Armazenamento de dados e Computação Avançada da UESC), composto por 20 servidores bi-processados Xeon5430 2,66GHz quad-core (FIGURA 3), com 2Gb de memória RAM por core, totalizando 160 cores e 320Gb conectados 4
21 via rede Infiniband, com sistema Red Hat Linux Enterprise Edition, versão 5.3, kernel FIGURA 2 Esquema do processador Intel i7-930 Fonte: Adaptada de Os compiladores utilizados foram o gcc (GNU Compiler Collection), versão 4.5.2, compilador de código aberto desenvolvido e distribuído pelo GNU Project, e a versão do icc, compilador C da Intel também disponível para utilização sem fins comerciais em PC Linux e adquirido sob licença para uso no C.A.C.A.U. Os detalhes da compilação serão abordados no capítulo 4. FIGURA 3 Esquema do processador Intel Xeon Fonte: Adaptada de A seguir, o sistema foi paralelizado através do padrão MPI, e para os testes foi utilizado um microcomputador com um processador Intel Core i7 CPU 2630QM (FIGURA 4), de 2.00 GHz com 4 núcleos, capazes de executar 2 threads por núcleo, memória RAM de 8 GB, memória cache de 6 MB. O compilador utilizado foi o gcc, versão chamado pelo MPICH2, versão 1.4. Os testes de desempenho foram realizados no cluster C.A.C.A.U. para até 32 processos simultâneos. 5
22 FIGURA 4 Esquema do processador Intel i7-2630qm. Fonte: Adaptada de Para selecionar os materiais existentes na literatura que abordam o tema desta dissertação, foi realizada uma pesquisa utilizando o método meta-analítico, cuja finalidade é dotar as revisões da pesquisa de rigor, objetividade e sistematização necessários. O Enfoque Meta-Analítico7f é composto de 7 fases: determinar as revistas científicas mais utilizadas no tema estudado; selecionar as que são mais relevantes; preencher Base de Dados com artigos (foi utilizada a base de dados ISI Web of Science, conhecida internacionalmente como uma das melhores e mais completas bases de dados de publicações); realizar análise de autores e artigos (examina a importância relativa do tema ao longo dos anos, ou seja, se nossa pesquisa possui interesse científico progressivo, e identifica quais os autores que lideram em termos quantitativos as revistas que registram os estudos de mais qualidade); identificar as principais linhas e enfoques teóricos que abordaram o tema; analisar as palavras chaves dos artigos; estudar as relações dos artigos previamente selecionados nas fases anteriores (MARIANO et al., 2011). 6
23 Os resultados deste estudo preliminar envolvem, entre outras informações, a frequência anual de trabalhos publicados sobre códigos PIC (FIGURA 5), a frequência anual de citações (FIGURA 6) e os autores mais citados no tema (TABELA 1). FIGURA 5 Quantidade de publicações sobre códigos PIC por ano. FIGURA 6 Quantidade de citações sobre códigos PIC por ano. TABELA 1 Publicações mais citadas sobre códigos PIC. Autor Ano Citações Birdsall, CK Vahedi, V; Surendra, M Vahedi, V; Birdsall, CK; Lieberman, MA; Dipeso, G; Rognlien, TD Meige, A; Boswell, RW; Charles, C; Turner, MM Chanrion, O.; Neubert, T Kawamura, E; Ingold, JH Radmilovic-Radjenovic, Marija; Radjenovic, Branislav Daube, T; Riemann, KU; Schmitz, H Vay, JL; Deutsch, C Behnke, JF; Csambal, C; Kudrna, P; Rusz, J; Tichy, M
24 Este trabalho está organizado da seguinte forma: No capítulo 1 é apresentada uma revisão bibliográfica sobre filmes finos, processos de deposição, e algumas técnicas de deposição do processo de Physical Vapor Deposition (PVD) como DC Sputtering, RF Sputtering e Magnetron Sputtering. No Capitulo 2 são apresentados os diversos tipos de arquiteturas paralelas. São descritos os paradigmas da memória distribuída e da memória compartilhada. São abordados os padrões OpenMP e MPI. São discutidos os principais fatores que afetam o desempenho e também são discutidas algumas de suas formas de mensuração e avaliação. No capítulo 3 é apresentada uma revisão bibliográfica sobre descrição cinética e códigos de partículas. Também são descritas as equações de movimento, bem como a relação entre as quantidades físicas e as grandezas na grade espacial. É apresentada uma revisão das estratégias de paralelização de códigos PIC e ainda o código computacional utilizado neste trabalho. No Capitulo 4 são descritas as estratégias de paralelização utilizadas, bem como suas implementações nos dois paradigmas de programação paralela utilizados neste trabalho. No Capítulo 5 são apresentados os resultados obtidos das execuções das aplicações, bem como as discussões quanto a estes resultados. Ao final, são mostradas as principais conclusões relativas aos resultados obtidos e apresentadas propostas para trabalhos futuros. 8
25 CAPÍTULO 1 FILMES FINOS Filmes finos (FIGURA 7) podem ser definidos como películas de determinados materiais, geralmente metálicos, podendo ser também poliméricos ou cerâmicos, depositadas sobre um substrato (amostra), com espessura muito menor que a do substrato, geralmente variando de alguns nanômetros até micrometros (MATTOX, 1998). Os filmes finos são produzidos pela condensação de espécies (atômicas, moleculares ou iônicas), por meio de um processo físico, químico, ou eletroquímico. Todavia, não é apenas a espessura de um filme que o define, mas sim a microestrutura resultante (HORA, 2008). FIGURA 7 Micrografias de filmes finos de ZrN depositados sobre um substrato de Si. Filme fino Substrato Fonte: Roman,
26 Os estudos sobre filmes finos iniciaram na década de 1920, na Inglaterra, por pesquisadores dos laboratórios Cavendish (OHRING, 1992). As aplicações tecnológicas e o interesse mais amplo pela comunidade científica foram ascender apenas nas décadas de 1970 e 1980 (HORA, 2008). Os filmes produzidos podem ser isolantes, semicondutores ou metálicos. Eles devem possuir características adequadas para uma dada utilização, tais como espessura e composição uniforme, poucos defeitos, baixa contaminação, boa aderência, baixa tensão e boa cobertura de degrau (HORA, 2008). São, portanto, utilizados para revestir materiais com a finalidade de melhorar suas propriedades físicas, químicas e mecânicas, tais como aumento de dureza, resistência a desgaste mecânico e abrasivo, proteção à corrosão, aumento da biocompatibilidade, entre outros (FEIL, 2006). O material revestido assume funcionalmente as mesmas propriedades do revestimento na interação com a vizinhança. Existem diversas aplicações para o revestimento com filmes finos, em vários segmentos da indústria, desde as áreas médica, odontológica à eletrônica e microeletrônica, óptica, sensores, decoração, mecânica (ROMAN, 2010). Podemos citar, na área biomédica, os seguintes usos de biomateriais depositados: implantes ortopédicos, válvulas cardíacas, próteses dentárias, películas antirreflexo em lentes oftalmológicas, entre outros. Nas demais áreas, temos, por exemplo, condutores e isolantes elétricos, microcircuitos, armações de óculos, jóias, ferramentas de cortes, filmes lubrificantes, entre muitos outros Processos de Deposição Existem diferentes processos que podem ser usados na deposição de filmes, em engenharia de superfícies: Deposição Atômica/Molecular (Atomistic/Moleular Deposition); Deposição de Particulados (Particulate Deposition); 10
27 Revestimentos de volume (Bulk Coatings); Modificação da superfície (Surface Modification). Apenas o primeiro processo será abordado, em virtude de ser objeto de nosso estudo. Um processo de deposição atômica de filme é aquele em que o material de revestimento é depositado átomo por átomo, e pode ser feito em um ambiente a vácuo, através de plasma, gás ou eletrolítico (MATTOX, 1998). Este processo consta de várias técnicas, entre elas as de deposição a vapor, que podem ser divididas em dois tipos: Physical Vapor Deposition (PVD) e Chemical Vapor Deposition (CVD). No processo de Deposição Física a Vapor (PVD), a deposição do material, inicialmente na fase sólida, é obtida por meio da evaporação deste, em unidades atômicas como partículas e moléculas, e a subsequente condensação sobre o substrato para formação de um filme. Um aspecto importante, é que o transporte dos vapores a partir do alvo ocorre através de um processo físico, e em um ambiente gasoso de baixa pressão (ou plasma) ou em um vácuo. Existem duas maneiras de vaporizar o material do alvo, uma é por evaporação térmica, chamada de evaporação a vácuo, e a outra é por arranque de átomos ou moléculas por transferência de momentum de partículas com alta energia incidentes no alvo, chamada de sputtering. Normalmente, os processos PVD são utilizados para depositar filmes com espessuras na faixa de alguns nanômetros a milhares de nanômetros; porém, eles também podem ser usados para formar os revestimentos multicamadas, depósitos de composição graduada, depósitos muito espessos e estruturas independentes. Taxas de deposição PVD típicas são Å (1-10 nanômetros) por segundo (MATTOX, 1998) Deposição assistida por plasma As características dos plasmas (neutralidade macroscópica, existência de partículas carregadas, comportamento coletivo) podem ser associadas a sólidos e líquidos, mas os plasmas estão efetivamente relacionados aos gases. Devido às suas propriedades singulares, considera-se o plasma como o quarto estado da matéria. Dado que é composto por partículas carregadas eletricamente (íons e 11
28 elétrons), geralmente em neutralidade macroscópica, é característica a sua interação com campos elétricos e magnéticos, e consequente auto-interação (NUNES, 2005). Um plasma é, portanto, um ambiente gasoso que contém íons e elétrons o suficiente para ser um bom condutor elétrico. A FIGURA 8 mostra uma lâmpada de plasma, onde as cores são resultado da emissão de fótons resultantes da relaxação de elétrons em estado de excitação para estados de menor energia. FIGURA 8 Lâmpada de plasma. Fonte: Muitas vezes, em um processamento PVD a plasma, o grau de ionização é baixo, de tal forma que há uma predominância dos gases neutros sobre os íons. Este plasma fracamente ionizado contém apenas uma pequena parte das suas partículas ionizadas, com o restante em estado neutro, algumas das quais podem ser excitadas. Um plasma eletricamente neutro é aquele que está macroscopicamente com carga neutra, tendo um número igual de cargas iônicas positivas e elétrons por unidade de volume. Em laboratório, na maioria das aplicações tecnológicas, os plasmas são mantidos pela introdução contínua de energia que acelera os elétrons a energias capazes de ionizar átomos pelas colisões elétron-átomo. As colisões inelásticas entre elétrons e átomos/moléculas no plasma produzem um grande número e variedade de espécies excitadas, radicais e íons, sem a necessidade de uma temperatura elevada do gás (CHEN, 1985; 12
29 ROSSNAGEL et al., 1990). Os plasmas presentes nas situações descritas aqui são comumente chamados de plasmas frios, em oposição à situação de reatores de fusão termonuclear controlada ou núcleos de estrelas, em que a temperatura chega a centenas de milhões de graus. Geralmente em processos de deposição PVD, plasmas são usados: Como fonte de íons de gases inertes (Ar +, Kr +, Hg + ) e/ou íons reativos (O +, N + 2 ) que podem ser acelerados a altas energias; Como uma fonte de elétrons; Como um meio para a limpeza de superfícies por "lavagem de íons," sputtering físico, ou cauterização a plasma; Como um meio de "ativar" espécies reativas através da formação de espécies excitadas, radicais e íons, adicionando energia térmica por processos de colisão; Para a criação de novas espécies químicas através de efeitos químicos do plasma, tais como Si 2 H 6 de SiH 4 ou O 3 de O 2, etc.; Como fonte de radiação ultravioleta Sputtering As primeiras observações do processo de deposição de filmes finos por sputtering são geralmente atribuídas a William Robert Grove, que em 1852, ao estudar tubos de luz fluorescente percebeu que o material de um dos eletrodos se depositava nas paredes de vidro dos tubos (ANDERS, 2007). O processo físico de sputtering, também conhecido por deposição por pulverização catódica, é a deposição de partículas vaporizadas a partir de um alvo (material a ser depositado). O sputtering físico é um processo de vaporização nãotérmica onde os átomos do alvo são fisicamente ejetados de uma superfície sólida por transferência de momentum a partir do bombardeamento de uma partícula 13
30 energética de tamanho atômico que geralmente é um íon gasoso acelerado a partir de um plasma. As partículas vaporizadas sofrem poucas colisões (ou nenhuma) no espaço entre o alvo e o substrato. O plasma usado em sputtering pode ser confinado perto da superfície do alvo ou pode preencher a região entre o alvo e o substrato. O material a ser depositado pode ser um elemento, liga, mistura, ou um composto, e pode ser evaporado em qualquer direção. Materiais compostos, tais como nitreto de titânio (TiN) e nitreto de zircônio (ZrN) são comumente depositados por pulverização catódica reativa usando um gás reativo no plasma. A presença do plasma "ativa" o gás tornando-o mais reativo quimicamente (MATTOX, 1998). O gás, geralmente pesado e inerte (Ar), é acelerado em direção ao alvo através de um campo elétrico (FIGURA 9). FIGURA 9 Esquema de um processo de deposição por sputtering de campo estático (DC). Fonte: Adaptada de As partículas de alta energia que bombardeiam o alvo, normalmente íons de Argônio (Ar + ), são geradas em plasmas de descarga luminosa (glow discharge). Para produzir a descarga luminosa é aplicado um campo elétrico DC (Direct Current) entre dois eletrodos (o alvo negativo, cátodo, e o substrato positivo, ânodo) dispostos em oposição dentro de uma câmara (TATSCH, 2006). A descarga luminosa se auto-sustenta a partir de determinado valor de corrente em um processo de avalanche. Um elétron livre acelerado colide com o Ar neutro arrancando-lhe um elétron e transformando-o em um íon. O elétron inicial, agora lento, e o que foi arrancado (elétron adicional) são novamente acelerados pelo potencial aplicado 14
31 produzindo, numa reação em cadeia, mais e mais íons de argônio, como mostra a equação e + Ar 0 2e + Ar +. (1) Os elétrons arrancados (elétrons secundários) ajudam a manter o plasma ao colidirem com os átomos neutros (MOURA, 2010). Quando o material do alvo não é condutor ou é de baixa condutividade, o DC Sputtering não pode ser aplicado, pois o material dielétrico fica carregado positivamente durante a descarga DC, diminuindo a diferença de potencial entre o cátodo e o ânodo até um valor abaixo do qual a descarga não mais se processa. Então, é necessário utilizar o RF Sputtering (radiofreqüência), que aplica um sinal alternado de alta freqüência, e a corrente pode passar através do alvo sem o acúmulo de cargas (MOURA, 2010; TATSCH, 2006). A ionização dos átomos de Argônio no plasma se processa pelas colisões com elétrons. Utilizando-se um campo magnético, os elétrons ficam confinados perto da superfície do alvo, e, com isso, a eficiência desta ionização aumenta. A técnica, para este caso, é denominada Magnetron Sputtering (FIGURA 10), e é aplicável tanto ao DC Sputtering como ao RF Sputtering (TATSCH, 2006). FIGURA 10 Magnetron sputtering elétrons confinados próximos à superfície do alvo pelo campo magnético dos ímãs. Fonte: Moura,
32 A deposição por pulverização catódica é amplamente utilizada na metalização de filmes finos em materiais semicondutores, revestimentos em vidro para construção, revestimentos anti-reflexo em discos compactos, filmes magnéticos, lubrificantes de filme seco e revestimentos decorativos. Esta técnica permite a deposição de uma grande variedade de materiais, incluindo alumínio, ligas de alumínio, platina, ouro, titânio, tungstênio, ligas de tungstênio, molibdênio, silício, óxido de silício e silicetos. Ela apresenta uma série de vantagens: Controle preciso da espessura pelo controle dos parâmetros de processo; Permite uma deposição uniforme e boa aderência do filme ao substrato; Controle das propriedades dos filmes como cobertura de degrau e estrutura de grão; Deposição de multicamadas com a utilização de alvos múltiplos; Semelhança ou a mesma identidade entre a estequiometria do filme e a do alvo. Quando a superfície do alvo é bombardeada por átomos, íons ou moléculas, vários fenômenos podem ocorrer na região desta superfície e na região próxima a ela (FIGURA 11). Estes fenômenos dependem da energia cinética das partículas incidentes. As partículas podem penetrar fisicamente a superfície, enquanto que os efeitos da colisão podem ser sentidos na região próxima da superfície. O bombardeamento da partícula cria uma cascata de colisões e algum momentum é transferido para os átomos da superfície, que podem ser ejetados sob a forma de vapor. A maioria da energia transferida (> 95%) aparece na forma de calor na região da superfície e na região perto da superfície. Algumas partículas são refletidas como átomos neutros de alta energia e algumas são implantadas na superfície. Os elétrons secundários gerados são responsáveis pelo plasma. Os átomos ejetados é que são interessantes para o processo de deposição por sputtering, pois saindo do 16
33 alvo vão se depositar em algum lugar na câmara, inclusive sobre o substrato (MARQUES, 2008). FIGURA 11 Eventos que ocorrem na superfície que é bombardeada com partículas energéticas de tamanho atômico. Fonte: Adaptada de Mattox, 1998 Quando uma partícula de tamanho atômico energética incide sobre uma superfície os efeitos do bombardeio da partícula podem ser classificados como: Efeitos imediatos (<10-12 s) colisões em rede, sputtering físico, reflexão da superfície; Efeitos de resfriamento (>10-12 a <10-10 s) picos térmicos ao longo de cascatas de colisões; Efeitos atrasados (>10-10 s a anos) difusão, difusão por tensão induzida, separação; Efeitos persistentes incorporação de gás, tensão de compressão devido à implantação de recuo. 17
34 CAPÍTULO 2 COMPUTAÇÃO PARALELA Muitas aplicações computacionais, presentes tanto em situações de interesse científico quanto comercial, consomem um tempo de execução muito longo quando processadas sequencialmente, tornando-as inviáveis. Outras possuem fortes requisitos computacionais, entre eles, grandes quantidades de memória, ou necessitam de respostas em intervalos de tempo bastante pequenos. A utilização do processamento paralelo pode viabilizar estas aplicações através da execução de várias operações simultaneamente, ou da divisão da carga de memória entre os elementos do conjunto computacional, por meio de um conjunto de técnicas, envolvendo hardware e software de um sistema computacional. Tradicionalmente, uma aplicação é escrita para ser executada em um único processador, e um problema é dividido em blocos de instruções, que são executados um após o outro (FIGURA 12). Por outro lado, na computação paralela um problema é dividido em blocos de instruções que podem ser executados simultaneamente em diferentes processadores, ou múltiplas unidades de processamento de um mesmo processador (FIGURA 13). 18
35 FIGURA 12 Partição das etapas na computação serial. Fonte: Adaptada de https://computing.llnl.gov/tutorials/parallel_comp/. FIGURA 13 Partição das etapas na computação paralela. Fonte: Adaptada de https://computing.llnl.gov/tutorials/parallel_comp/. Para evitar os problemas decorrentes dos limites físicos do aumento da performance dos processadores, especialmente na miniaturização dos transistores, os projetistas de computadores estão se voltando cada vez mais para as máquinas paralelas. Muitos tipos diferentes de computadores paralelos têm sidos desenhados e construídos ao longo dos últimos anos, como por exemplo, os propostos por Flynn, Gajski e Pier, e Treleaven (TANENBAUM, 2001) Arquiteturas Flynn (HENNESSY; PATTERSON, 2008; STALLINGS, 2002) propôs uma classificação das arquiteturas paralelas, que tem como base a relação entre o fluxo de instruções e o fluxo de dados: 19
36 Única Instrução Único Dado (SISD Single Instruction Single Data) Uma instrução é executada por vez e para cada instrução há um único dado sendo operado. Utiliza um único processador. Única Instrução Múltiplos Dados (SIMD Single Instruction Multiple Data) Uma instrução é capaz de realizar operações simultâneas sobre elementos de vetores e matrizes (múltiplos dados). A arquitetura vetorial e a matricial possuem paralelismo implícito, transparente ao programador. Múltiplas Instruções Único Dado (MISD Multiple Instruction Single Data) Várias instruções são operadas sobre o mesmo dado. Cada processador modifica o dado e o passa para o próximo processador, realizando operações diferentes. Não existe na prática, é uma máquina hipotética. Múltiplas Instruções Múltiplos Dados (MIMD Multiple Instruction Multiple Data) Várias linhas de instruções operam independentemente sobre conjuntos de dados possivelmente disjuntos. Tais execuções paralelas podem ocorrer através de multiprocessadores ou multicomputadores. Cada processador executa suas instruções independentemente dos demais, exigindo que o programador aponte explicitamente como o paralelismo é gerenciado. Na FIGURA 14, podemos ver as quatro categorias desta classificação de Flynn (PASSOS, 2006). 20
37 Múltiplos Fluxo de Instruções Simples FIGURA 14 Classificação de Flynn. Fluxo de Dados Simples Múltiplos SISD SIMD i P d M d P i d M i,d M i i i P P d d M d M d MISD M d d P i M i d P i M i d d P i M i MIMD M i,d M i,d i d i d P P d d d P P d i d i d M i,d M i,d Fonte: Passos, P: processador M: memória i: instruções d: dados E.E. Johnson propôs uma classificação para a classe MIMD, de Flynn, baseada na estrutura de memória, global ou distribuída, e no mecanismo utilizado para a comunicação e sincronização, variáveis compartilhadas ou troca de mensagens (PASSOS, 2006): Global Memory Shared Variable (GMSV) São as máquinas que possuem vários processadores que compartilham a mesma memória; Global Memory Message Passing (GMMP) Não existe, na prática, um computador com esta classificação; Distributed Memory Shared Variable (DMSV) Engloba múltiplos computadores interconectados e que compartilham a memória distribuída; Distributed Memory Message Passing (DMMP) Engloba múltiplos computadores interconectados e que se comunicam via troca de mensagens, são os multicomputadores de memória distribuída. 21
38 Fluxo de Instruções Múltiplos Distribuída Memória Global Simples A FIGURA 15 mostra esta classificação, conhecida como Flynn-Johnson. FIGURA 15 Classificação de Flynn-Johnson. Simples Fluxo de Dados Múltiplos SISD SIMD GMSV GMMP MISD DMSV MIMD DMMP Variável compartilhada Comunicação/Sincronização Troca de mensagem Fonte: Passos, As arquiteturas paralelas podem ser organizadas como: Multiprocessada É um conjunto de processadores agregados a um barramento comum, que operam sobre uma unidade de memória, sendo que a memória pode ser acessada uniformemente (Uniform Memory Access - UMA), ou seja, o tempo de acesso aos dados localizados em qualquer posição da memória é o mesmo para todos os processadores, ou nãouniformemente (Non-Uniform Memory Access - NUMA), quando o tempo de acesso à memória depende da posição em que a mesma se encontra em relação ao processador (STALLINGS, 2002). Nestes casos, o número de processadores que a máquina terá é decidido no ato da sua concepção, não sendo possível adicionar mais processadores posteriormente. Esta arquitetura não se comporta bem para um grande número de processadores, visto que o barramento fica sobrecarregado. Para contornar este problema, usualmente os processadores têm grande quantidade de memória cache. A FIGURA 16(a) ilustra esta arquitetura, onde os processos P acessam a memória (M) através de um barramento comum. 22
39 o Multi-core É formada por processadores com múltiplos núcleos de processamento. Nesta arquitetura, todo o conjunto de recursos (unidade de controle, unidade aritmética e lógica, etc.) é replicado, como se vários processadores estivessem integrados em um único chip. Com isso, múltiplos programas ou fluxos de execuções podem ser executados simultaneamente, de acordo com o número de núcleos existente. E os recursos de cache podem ser compartilhados entre os diferentes núcleos, então, diferentes fluxos de instrução podem ser executados sobre os mesmos dados em cache (AKHTER; ROBERTS, 2006). A FIGURA 16(d) apresenta um processador formado internamente por quatro núcleos de processamento. FIGURA 16 Esquema de arquiteturas (a) multiprocessador; (b) multicomputador; (c) vetorial; (d) multicore; (e) cluster. (a) (b) (c) P P P P P M M M M M UC Barramento P P P P P P P P P P M M M M M Rede de Interconexão M M M M M (d) (e) Núcleo0 Núcleo1 cache L2 Núcleo2 Núcleo3 cache L2 C C C C C Barramento Rede M Fonte: Adaptada de SCHEPKE, Multicomputador É um conjunto de computadores independentes interconectados através de uma rede. Cada computador acessa somente a sua própria memória, e é através de uma rede de interconexão que os processadores enviam mensagens entre si, trocando dados necessários ao 23
40 processamento. As mensagens trocadas entre os processadores são ditadas pelo código do programa. A idéia, com isso, é dividir o problema em várias partes e, durante a execução, quando necessário, realizar a troca de mensagens (AKHTER; ROBERTS, 2006). A FIGURA 16(b) ilustra esta arquitetura, onde cada processador P tem sua memória local M e só pode acessar os dados de outra máquina através de uma interconexão de rede. Podem ser divididos em duas categorias: Processadores Fortemente Paralelos (Massively Parallel Processors MPP), que são supercomputadores extremamente caros, compostos por muitos processadores fortemente acoplados por intermédio de uma rede de interconexão de alta velocidade, geralmente proprietária; e Clusters de Estações de Trabalho (Cluster of Workstations COW), que são PCs ou estações de trabalho, montados em prateleiras ou racks, e ligados por intermédio de redes comerciais (TANENBAUM,2001). o Cluster É um tipo de sistema de processamento distribuído, que consiste de um conjunto de computadores interconectados, que cooperam entre si na execução de aplicações utilizando a troca de mensagens por uma rede de alta velocidade. As máquinas de um cluster são frequentemente homogêneas, possuindo os mesmos recursos de memória, processamento, cache e rede, e são geridas por uma entidade administrativa única que tem completo controle sobre o mesmo (PASSOS, 2006). O gerenciamento do cluster envolve diversas atribuições, entre elas, o monitoramento e escalonamento de tarefas. Os objetivos de um escalonador são maximizar a utilização do cluster, maximizar a quantidade de aplicações executadas, reduzir o tempo de resposta, mesclar requisições dos usuários com as ordens administrativas e dar a ilusão de uma máquina única e dedicada. Esta arquitetura é flexível, máquinas podem ser adicionadas ou removidas, sem a interferência no restante do 24
41 conjunto (SCHEPKE, 2009). A FIGURA 16(e) ilustra uma arquitetura genérica de cluster. o Grid É um conjunto de clusters de diversas configurações, ou mesmo um conjunto muito grande de máquinas geograficamente distribuídas. O que difere um cluster de um grid é basicamente a infra-estrutura da rede, a qual tem uma dimensão local (e restrita) no caso de um cluster, e que atinge proporções globais para um grid. Um Grid é uma infra-estrutura de hardware e software capaz de prover uma grande capacidade de processamento (TeraFlops), a qual é necessária para a resolução de aplicações que necessitam dessa soma de recursos. Entre as dificuldades para a construção de uma infra-estrutura de grid, pode-se destacar o gerenciamento dos recursos, a grande heterogeneidade de máquinas e de conexões de rede, a grande escalabilidade, o controle de acesso aos administradores e usuários e as interfaces de programação (KARNIADAKIS; KIRBY, 2007). A FIGURA 17 descreve esta arquitetura. Vetorial Esta arquitetura provê instruções de alto nível sobre vetores de dados. As operações aritméticas, em um vetor ou entre vetores, são realizadas sem a implementação de um laço, o que já é necessário nas arquiteturas não vetoriais. Esta arquitetura explora o paralelismo de dados ao invés do paralelismo de tarefas. A redução do número de instruções por programa e de falhas de cache de dados são algumas das vantagens desta arquitetura (TANENBAUM, 2001). A FIGURA 16(c) ilustra esta arquitetura, onde uma unidade de controle UC é responsável pelo gerenciamento dos processadores, os quais podem executar sobre regiões de memória distintas. 25
42 FIGURA 17 Esquema de arquitetura grid. Fonte: Adaptada de SCHEPKE, Paradigmas Uma das características mais importantes de um computador paralelo é a forma como a memória é organizada. As técnicas de processamento paralelo mais utilizadas são classificadas através de três paradigmas de memória (BARNEY, 2009a; SENA; COSTA, 2008; TANENBAUM, 2001): Memória distribuída técnica utilizada em computadores com vários processadores que possuem seu próprio recurso de memória e são interconectados através de uma rede local (FIGURA 18). O padrão MPI (Message Passing Interface) tem sido o mais utilizado e seu funcionamento se dá através da troca de dados e tarefas entre as unidades de processamento. Outros padrões bastante conhecidos são o PVM (Parallel Virtual Machine), Parmacs (PARallel MACroS), Zipcode, Chimp, Chameleon e outros. Memória compartilhada técnica utilizada em ambientes que possuem vários núcleos de processamento compartilhando o mesmo recurso de memória (FIGURA 19). O padrão OpenMP (Open Multi Processing) tem sido bastante utilizado, estando integrado na maioria dos compiladores livres ou comerciais. 26
43 Memória distribuída + compartilhada (híbrida) Sistema em dois níveis, em que a memória é segmentada entre os nós, e a informação transita pela rede, mas dentro do nó existe mais de uma unidade de processamento, que compartilham a memória local. Técnica utilizada em computadores onde as memórias são distribuídas fisicamente em cada nó, mas todos os processadores podem endereçar essa memória oferecendo a abstração de um espaço de endereçamento lógico, a que todos os processadores de uma arquitetura distribuída têm acesso, apesar de fisicamente a memória ser local a cada um deles. FIGURA 18 Memória Distribuída. Fonte: Adaptada de https://computing.llnl.gov/tutorials/parallel_comp/. FIGURA 19 Memória Compartilhada (a) UMA (b) NUMA. Fonte: Adaptada de https://computing.llnl.gov/tutorials/parallel_comp/. Um computador com uma arquitetura de memória compartilhada tem um único espaço de endereço, a partir do qual todos os processadores leem os dados, e na qual todos eles escrevem. Em uma arquitetura de memória distribuída, por outro lado, há muitos espaços de endereço disjuntos, geralmente organizados de forma que cada processador tem exatamente uma memória privada. Os processadores apenas têm acesso direto às suas próprias memórias, e devem interagir com outros enviando mensagens ou fazendo pedidos de alguma forma para acessar valores em 27
44 outros espaços de endereçamento, via rede (WILSON; LU, 1996). Um sistema de memória compartilhada distribuída (Distributed Shared Memory DSM) implementa logicamente um sistema de memória compartilhada sobre um sistema de memória distribuída. O sistema DSM permite a integração da escalabilidade das arquiteturas de memória distribuída com a maior facilidade de programação do paradigma de memória compartilhada (TANENBAUM, 2001). A distinção fundamental entre diferentes máquinas de memória compartilhada é se os tempos de acesso para diferentes partes da memória podem variar, se são UMA ou NUMA, como já explanado anteriormente. Para atingir um alto desempenho em multiprocessadores NUMA, importa saber se o dado que está sendo acessado é local ou remoto. Outra maneira de pensar sobre paradigmas de programação paralela é olhar para quantas coisas diferentes podem estar acontecendo ao mesmo tempo, e para quantas coisas diferentes uma operação individual pode ser aplicada. Os quatro modelos mais importantes são (WILSON; LU, 1996): tarefa paralela: um modelo em que muitas operações diferentes podem ser executadas simultaneamente. método paralelo: um modelo em que todos os objetos que são membros de um conjunto executam o mesmo método (que pode ou não pode representar sobrecarga), ao mesmo tempo. Paralelismo de método e paralelismo de tarefa são exemplos de paralelismo de controle. fluxo de dados: um modelo em que os programas são representados como gráficos de dependência, e cada operação é automaticamente bloqueada até que os valores de que ela depende estão disponíveis. dados paralelos: um modelo em que uma única operação pode ser aplicada a muitos elementos de uma estrutura agregada de uma vez. Uma técnica de programação paralela muito utilizada em memória compartilhada com acesso NUMA é aquela baseada em diretivas. Diretivas de 28
45 compilação são inseridas no código sequencial para informar ao compilador quais regiões devem ser paralelizadas. Com base nestas diretivas o compilador gera um código paralelo. Este compilador deve ser capaz de entender as diretivas e gerar o código multi-thread (multilinha, ou multisequencia, numa tradução livre). O padrão OpenMP é uma interface utilizada para especificar estas diretivas, funções e variáveis de ambiente Memória Compartilhada OpenMP O OpenMP não é uma nova linguagem de computador, mas uma extensão, que trabalha sobre Fortran ou C/C++ (ou outras linguagens) para capacitá-las como linguagens de programação multi-thread, ou seja, o modelo de linguagem é baseado na hipótese de que as UEs (unidades de execução) são threads (linhas de execução) que compartilham um espaço de endereço (KARNIADAKIS; KIRBY, 2007). O OpenMP é composto de um conjunto de diretivas de compilador que descrevem o paralelismo no código fonte, juntamente com uma biblioteca de funções de apoio disponíveis para as aplicações. Coletivamente, essas diretivas e as rotinas de biblioteca são formalmente descritas pela interface de programação de aplicação (API), agora conhecida como OpenMP (CHANDRA et al., 2001). As diretivas são notas de instrução para qualquer compilador que suporte OpenMP. Eles tomam a forma de sentinela!$omp (em Fortran) ou #pragma omp (em C/C++), a fim de aumentar a portabilidade do aplicativo quando migrar para ambientes que não tenham OpenMP (CHANDRA et al., 2001). O padrão OpenMP é desenvolvido e mantido pelo grupo OpenMP ARB (Architecture Review Board), formado por alguns dos maiores fabricantes de software e hardware do mundo, tais como SUN Microsystems, SGI, IBM, Intel, dentre outros, que, no final de 1997, reuniram esforços para criar um padrão de programação paralela para arquiteturas de memória compartilhada. O Open significa que é padrão e está definido por uma especificação de domínio público e MP são as siglas de Multi Processing (SENA; COSTA, 2008). 29
46 Converter um programa sequencial em paralelo utilizando o OpenMP é relativamente simples, se comparado com outras técnicas. Basta incorporar as diretivas no código sequencial, efetuando pequenas modificações. O êxito do OpenMP é demonstrado pela sua difusão pelas arquiteturas multicore e pode ser atribuído a fatores como a facilidade do seu uso; a despreocupação com sincronização de mensagens, em relação à interface MPI; a flexibilidade, mesmo com relação às aplicações sequenciais, pois um compilador comum interpretará as diretivas OpenMP apenas como comentários; e a possibilidade de paralelizar diversos trechos de código sem modificá-los estruturalmente, diminuindo a incidência de erros de programação (GOLDMAN et al., 2010). A paralelização, em OpenMP, é realizada explicitamente com múltiplas threads (linhas) dentro de um mesmo processo. O processo é dividido em tarefas que podem ser executadas simultaneamente e distribuídas pelas threads. Cada thread possui sua própria pilha de execução, porém compartilha o mesmo endereço de memória com as outras threads do mesmo processo, e cada processo possui seu próprio espaço de memória. O programa se inicia com a thread mestre executando as instruções até encontrar a diretiva de região paralela, então ela cria um grupo de threads que juntas executam o código dentro dessa região. Quando elas terminam suas execuções, no final da região paralela, as threads esperam até que todo o conjunto atinja o final, e então elas sincronizam-se e somente a thread mestre segue na execução do código até que uma nova diretiva seja encontrada ou o programa encerre (SENA; COSTA, 2008). Esse modelo de programação é conhecido como fork-join (do inglês separar-juntar, veja FIGURA 20). O objetivo dos criadores do OpenMP foi fazer o OpenMP fácil para os programadores de aplicativos utilizarem. Desempenho final é importante, mas não se faria a linguagem difícil para engenheiros de software usarem, nem criarem programas paralelos ou mantê-los. Para este fim, OpenMP foi projetado em torno de dois conceitos-chave: equivalência sequencial e paralelismo incremental. Um programa é dito ser sequencialmente equivalente quando ele produz os mesmos resultados, quer ele execute utilizando uma thread ou muitas threads. Um programa 30
47 sequencialmente equivalente é mais fácil de manter e, na maioria dos casos, muito mais fácil de entender e, portanto, de escrever (MATTSON et al., 2005). FIGURA 20 Modelo de programação OpenMP. FONTE: Sena; Costa, O paralelismo incremental refere-se a um estilo de programação paralela em que um programa evolui a partir de um programa sequencial em um programa paralelo. Um programador começa com um programa sequencial e bloco por bloco encontra pedaços de código que compensem serem executados em paralelo. Assim, o paralelismo é adicionado de forma incremental. Em cada fase do processo, há um programa que pode ser verificado, aumentando consideravelmente as chances de que o projeto será bem sucedido (MATTSON et al., 2005). Nem sempre é possível usar o paralelismo incremental ou criar programas OpenMP sequencialmente equivalentes. Às vezes, um algoritmo paralelo exige uma reestruturação completa do programa sequencial análogo. Em outros casos, o programa é construído a partir do paralelo e não há um programa sequencial para o paralelismo incremental. Além disso, existem algoritmos paralelos que não funcionam com uma thread e, portanto, não podem ser sequencialmente equivalentes. Ainda assim, o paralelismo incremental e a equivalência sequencial guiou o modelo da API OpenMP e são práticas recomendadas (MATTSON et al., 2005). Uma situação que deve ser considerada com cuidado é o acesso às variáveis compartilhadas, que precisa ser realizado de maneira organizada e sincronizada pelas threads, a fim de evitar as condições de corrida (race conditions), que 31
48 acontecem quando duas ou mais threads tentam atualizar, ao mesmo tempo, uma mesma variável ou quando uma thread atualiza uma variável e outra thread acessa o valor dessa variável ao mesmo tempo. Quando uma dessas situações ocorre, o resultado vai depender da ordem de execução das threads e não há nenhuma garantia que a variável seja atualizada com o valor correto. As diretivas de sincronização (critical, atomic, flush) garantem que o acesso ou atualização de uma determinada variável compartilhada seja realizado de maneira correta (SENA; COSTA, 2008; CHANDRA et al., 2001). Como dito anteriormente (seção 2.2), o OpenMP é constituído de variáveis de ambiente, diretivas de compilação e bibliotecas de serviço, que juntas integram todas as funcionalidades disponíveis do padrão OpenMP. O QUADRO 1 ilustra a sintaxe desses elementos para a linguagem C/C++ (BARNEY, 2009c; SENA; COSTA, 2008). QUADRO 1 Elementos da interface OpenMP Elementos Sintaxe Exemplo variáveis de ambiente OMP_NOME OMP_NUM_THREADS diretivas de compilação #pragma omp diretiva [cláusula] #pragma omp parallel biblioteca de funções omp_serviço (...) omp_get_num_threads() Memória Distribuída MPI O MPI (Message Passing Interface ou interface de envio de mensagens) é o ambiente de programação padrão mais utilizado para computadores paralelos de memória distribuída, e é usualmente empregado em computação de alto desempenho (HPC High-Performance Computing). A construção central em MPI é a passagem de mensagens: Um processo empacota a informação requerida em uma mensagem e a envia para outro processo. O MPI, no entanto, inclui muito mais do que simples troca de mensagens, pois inclui rotinas para sincronizar processos, 32
49 somar números distribuídos entre um conjunto de processos, dispersar dados entre um conjunto de processos, e muito mais (MATTSON et al., 2005; PACHECO, 1997). O MPI foi criado no início dos anos 90 para fornecer um ambiente de transmissão de mensagens comum que poderia ser executado em clusters, MPPs (Processadores Massivamente Paralelos), e até mesmo máquinas de memória compartilhada. Ele é baseado em convenções da MPI Fórum 1, que possui mais de 40 organizações participantes, entre fornecedores, pesquisadores, desenvolvedores e usuários. Cada implementação do MPI é distribuída na forma de uma biblioteca, e a especificação oficial define vinculações para C, C++ e Fortran (GOLDMAN et al., 2010). Existem várias implementações de MPI de uso comum. As mais conhecidas são LAM/MPI [LAM], MPICH [MPI] e, mais recentemente, o OpenMPI. Todas podem ser acessadas gratuitamente e são relativamente simples de instalar. Elas possuem código aberto e suportam uma ampla gama de computadores paralelos, incluindo clusters com variados sistemas operacionais, computadores NUMA, e SMPs (Multiprocessadores Simétricos) (MATTSON et al., 2005). A idéia básica de passar uma mensagem é extremamente simples: um processo envia uma mensagem e outro processo a recebe. Indo mais fundo, no entanto, os detalhes por trás da passagem de mensagens se tornam muito mais complicados: Como as mensagens são armazenadas no buffer dentro do sistema? Um processo pode executar outra tarefa enquanto ele está enviando ou recebendo mensagens? Como as mensagens podem ser identificadas de modo que quem envia está sempre emparelhado com quem ele deseja que receba? (MATTSON et al., 2005). O sucesso a longo prazo do MPI é devido à sua solução elegante para esses e outros problemas. A abordagem é baseada em dois elementos centrais do MPI: grupos de processos e um contexto de comunicação. Um grupo de processos é um conjunto de processos envolvidos em um cálculo. No MPI, todos esses 1 33
50 processos envolvidos no cálculo são lançados juntos quando o programa começa e pertencem a um único grupo. Como o cálculo prossegue, no entanto, o programador pode dividir os processos em subgrupos e controlar com precisão como os grupos interagem (MATTSON et al., 2005). Um contexto de comunicação fornece um mecanismo para agrupar conjuntos de comunicações relacionadas. Em qualquer sistema de passagem de mensagens, as mensagens devem ser rotuladas para que elas possam ser entregues ao destino ou destinos. Os rótulos de mensagem em MPI consistem na identificação do processo de envio, a identificação do destinatário pretendido, e uma expressão inteira (tag). A instrução de receber inclui parâmetros que indicam uma origem e uma tag. O resultado, então, de executar uma instrução de receber no processo i é a entrega de uma mensagem com destino i cuja origem e tag correspondem aquelas que estão na instrução (MATTSON et al., 2005). Embora simples, identificar mensagens com origem, destino, e tag pode não ser adequado em aplicações complexas, particularmente aquelas que incluem bibliotecas ou outras funções reutilizadas de outros programas. Muitas vezes, o programador da aplicação não conhece nenhum dos detalhes sobre esse código emprestado, e se a biblioteca inclui chamadas para MPI, existe a possibilidade de mensagens na aplicação e a biblioteca poderem acidentalmente compartilhar tags, identificações de destinos, e identificações de fonte. Isto poderia levar a erros quando uma mensagem de biblioteca é entregue ao código da aplicação, ou viceversa. Uma maneira de lidar com este problema para os escritores de biblioteca é especificar as tags reservadas que os usuários devem evitar em seu código. Esta abordagem revelou-se trabalhosa, no entanto, e é propensa a erros, porque requer que os programadores leiam e sigam atentamente as instruções na documentação (MATTSON et al., 2005). A solução do MPI para este problema é baseado na noção de contextos de comunicação. Cada envio (e sua mensagem resultante) e recebimento pertencem a um contexto de comunicação e apenas estes eventos de comunicação que compartilham um contexto de comunicação se corresponderão. Assim, mesmo se as 34
51 mensagens compartilham uma fonte, um destino, e uma tag, eles não serão confundidos uns com os outros, enquanto eles têm diferentes contextos. Contextos de comunicação são criados dinamicamente e com garantia de serem únicos (MATTSON et al., 2005). Em MPI, o grupo de processos e o contexto de comunicação são combinados em um único objeto chamado de comunicador. Com poucas exceções, as funções em MPI incluem uma referência a um comunicador. Na inicialização do programa, o sistema de execução cria um comunicador comum chamado MPI_COMM_WORLD (MATTSON et al., 2005). A troca de mensagens é baseada nas primitivas send e receive. Todos os processadores podem trocar informações com todos os outros processadores simultaneamente (FERREIRA, 2006). Uma aplicação implementada com MPI é constituída por processos que se comunicam, e que põem em ação funções para o envio e recebimento de mensagens entre eles. Inicialmente é definida a quantidade de processos que vão executar a aplicação, sendo que cada um deles pode executar diferentes programas. O MPI suporta tanto a comunicação ponto-a-ponto quanto a coletiva, ou seja, os processadores podem efetuar operações para enviar mensagens de um determinado processo a outro, ou um grupo de processos pode efetuar operações de comunicações globais. O MPI também é capaz de suportar comunicação assíncrona (GOLDMAN et al., 2010). As vantagens de se utilizar o MPI são: Portabilidade: Uma aplicação pode ser executada em diferentes plataformas sem a necessidade de se reescrever o código, desde que estas plataformas suportem o padrão MPI; Disponibilidade: Existem muitas implementações disponíveis; Funcionalidade: Mais de 115 rotinas estão definidas só na primeira versão do padrão, o MPI-1; 35
52 Padronização: É a única especificação de passagem de mensagens considerada um padrão. Existem duas versões do MPI que são populares atualmente: MPI-1, que dá ênfase a passagem de mensagem e tem um ambiente estático de execução; e o MPI-2, concluída em 1996, que inclui gerenciamento dinâmico de processos, entre outras inovações, e especifica mais de 500 funções. Os programas em MPI-1 continuam funcionando em implementações de MPI-2 (BARNEY, 2009b) Métricas de Desempenho As métricas de desempenho são estatísticas que ajudam a caracterizar o tempo de execução da aplicação paralela. Elas são úteis para descobrir alguns tipos de gargalos. Durante o processo de medir o desempenho de uma aplicação, vários tipos de parâmetros podem ser medidos. Uma boa medida é a velocidade média, que é a velocidade alcançada dividida pelo número de processadores. O ideal é que a velocidade média se mantenha constante à medida que o tamanho do sistema aumente. Se o tamanho do problema é fixo, a razão comunicação/computação cresce com o aumento do número de processadores, e então, a velocidade média diminui com o aumento do tamanho do sistema. Por outro lado, se o tamanho do sistema é fixo, a razão comunicação/computação decresce com o aumento do tamanho do problema (FERREIRA, 2006). A métrica de desempenho mais comumente utilizada para o processamento paralelo é o speedup, que mede se houve melhoria de desempenho devido ao paralelismo. O speedup é definido como o desempenho absoluto obtido com a utilização de um único processador (com programa serial) dividido pelo desempenho obtido com a utilização de p processadores, n n, p O QUADRO 2 mostra os possíveis resultados. T S n, p. (2) T 36
53 QUADRO 2 Classificação do speedup. Resultado Classificação Avaliação S(n,p) < 1 Slowdown Indesejável 1 < S(n,p) < p Sublinear Comportamento mais comum S(n,p) = p Linear Ideal, não existe sobrecarga S(n,p) > p Supralinear Situação possível, mas rara. FONTE: Adaptado de A eficiência é o parâmetro de desempenho que mede a utilização média do processador, e é definida como a razão do speedup sobre o número de processadores ou processos. Para medirmos a eficiência utilizamos S n, p E n, p. (3) p O valor obtido da eficiência normalmente se encontra entre os resultados mostrados no QUADRO 3. Ele é frequentemente transformado em um valor percentual. QUADRO 3 Classificação da Eficiência. Resultado Classificação Avaliação E(n,p) < 1/p Slowdown Indesejável 1/p < E(n,p) < 1 Sublinear Comportamento geral E(n,p) = 1 Linear Ideal E(n,p) > 1 Supralinear Situação possível, mas rara. FONTE: Adaptado de Dois dos principais objetivos de aplicações paralelas são o desempenho e a escalabilidade. O primeiro é a capacidade de reduzir o tempo de resolução do 37
54 problema à medida que os recursos computacionais aumentam. E o segundo é a capacidade de ter os recursos aumentados ou melhorados para absorver qualquer demanda de desempenho, ou reduzidos para diminuir custos (FERREIRA, 2006; HWANG; XU, 1998). Um programa é dito escalável se podemos manter constante a eficiência E(n,p), incrementando o tamanho do problema n ao mesmo tempo que incrementamos o número de processos p Avaliação de Desempenho O objetivo de utilizar computação paralela através de multiprocessadores ou multicomputadores é diminuir o tempo de execução. Avaliar o desempenho de um sistema paralelo é coletar informações sobre um conjunto de computações que informarão que decisão tomar quanto à paralelização das diversas regiões do sistema. Segundo Ferreira (2006, p. 30), muitos fatores influenciam o desempenho e é difícil avaliar se e onde as aplicações experimentaram desempenho pobre. Os principais fatores que afetam o desempenho paralelo são cobertura, granularidade, balanceamento de carga, localidade e sincronização. Os três primeiros são fundamentais para a programação paralela em qualquer tipo de máquina. Os dois últimos são altamente ligados com o tipo de hardware que estamos considerando. Seus efeitos são muitas vezes mais surpreendentes e mais difíceis de entender, e seu impacto pode ser enorme (CHANDRA et al., 2001). Cobertura é a percentagem de um programa que é paralelo. A fim de obter um bom desempenho em um código paralelo, é necessário paralelizar uma parte suficientemente grande do código. Este é um conceito bastante óbvio, mas o que é menos óbvio e que é, talvez, até mesmo absurdo é que, como o número de processadores aumenta, o desempenho da aplicação pode tornar-se influenciado pelas partes seriais do programa, mesmo quando essas partes forem relativamente sem importância na execução serial do programa. Esta idéia é apreendida na lei de Amdahl (CHANDRA et al., 2001; HENNESSY; PATTERSON, 2008). Se F é a fração 38
55 do código que é paralelo e S p é o speedup alcançado nas seções paralelas do código, o speedup geral S é dado por S 1 F 1 F S p. (4) A fórmula pode ser facilmente derivada da seguinte forma. Em uma execução serial, o programa irá executar no tempo T s. Em uma execução paralela, a parte serial (1 F) do código irá executar no tempo (1 F)T s, enquanto que a parte paralela (F) irá executar no tempo FT s. (5) S p A soma dessas duas quantidades fornece o tempo de execução paralelo: FT s 1 F Ts. (6) S p Dividindo o tempo de execução serial pelo tempo de execução paralela obtemos a lei de Amdahl (CHANDRA et al., 2001). A mensagem principal na lei de Amdahl é que, independente de quão bem paralelizamos a parte paralela de um código e não importa quantos processadores usamos, o desempenho da aplicação será completamente limitado por F, a fração do código que somos capazes de paralelizar. Se, por exemplo, somos capazes de paralelizar o código para metade do tempo de execução do aplicativo, o speedup geral nunca poderá ser melhor do que dois, porque não importa o quão rápido a parte paralela é executada, o programa gastará metade do tempo serial original na parte serial do código paralelo (CHANDRA et al., 2001). Contudo, segundo a lei de Gustafson (WILKINSON; ALLEN, 1999), se mantermos fixo o tempo de execução do problema, o speedup não será mais limitado pelo percentual do grau de paralelização da parte paralelizável, mas pelo tamanho do problema: 39
56 S p p 1, (7) onde α é a fração sequencial do programa. Desta maneira, apesar de porções não paralelizadas do código manterem seu custo, pode-se alcançar uma quantidade muito maior de resultados na porção paralela, resultando num efetivo ganho de produção num dado tempo total de execução. Cobertura elevada por si só não é suficiente para garantir um bom desempenho. Granularidade é outra questão que afeta o desempenho, e ela se refere à quantidade de trabalho que existe em cada região paralela, em comparação com a quantidade de comunicação. Toda vez que o programa invoca uma região ou laço paralelo, incorre em certa sobrecarga (overhead) para paralelizar. Assumindo que a cláusula nowait não foi utilizada, todas as threads devem executar uma barreira ao final da região paralela ou loop. Se a cobertura é perfeita, mas o programa chama um número muito grande de pequenos loops paralelos, então o desempenho pode ser limitado pela granularidade. O cálculo do custo exato de invocar um loop paralelo é realmente bastante complicado. Além dos custos de invocar o loop paralelo e executar a barreira, os efeitos de cache e sincronização podem aumentar muito o custo. Em geral, não se deve paralelizar um laço ou região, a menos que leve muito mais tempo para executar do que o overhead paralelo. E pode-se reduzir significativamente o overhead usando a abordagem de granulação grossa, isto é, executar muitas instruções com pouca troca de informação (BARNEY, 2009a; CHANDRA et al., 2001). Para medirmos a granularidade utilizamos (WILKINSON; ALLEN, 1999) n n Tcp G n, (8) T cm onde G é a granularidade; n é o tamanho do problema; T cp é o Tempo de computação; T cm é o Tempo de comunicação. O balanceamento de carga consiste na distribuição equilibrada de carga de trabalho entre os processadores. Tipicamente, o loop paralelo não será concluído 40
57 até que o último processador complete suas iterações. Se alguns processadores têm mais trabalho a fazer do que outros processadores e o desempenho será prejudicado. As iterações dos loops podem ser divididas entre os diferentes processadores de forma estática ou dinâmica. Na forma estática, as iterações são divididas entre os processadores no início da região paralela, e ela pode conseguir uma boa distribuição da carga em situações onde a quantidade de trabalho por iteração é uniforme ou se esta quantidade varia de forma previsível. Quando o trabalho por iteração varia de forma imprevisível, e uma thread fica com mais trabalho do que outra, ela pode terminar muito mais tarde do que a outra, então um esquema dinâmico provavelmente consegue um melhor balanço de carga (CHANDRA et al., 2001). Para medirmos o balanceamento de carga utilizamos (WILKINSON; ALLEN, 1999) F LB n n T T n n Tmax min, (9) max onde F LB é o fator de balanço de carga ou razão de sincronização; T max é o Tempo do último processo terminar; T min é o Tempo do primeiro processo terminar. Quando o resultado de F LB é zero significa uma situação ótima, pois T max é aproximadamente igual a T min. E quando o resultado é 1 (um) significa uma situação indesejada, pois T max é muito maior do que T min. É necessário levar em consideração os custos de utilização do esquema dinâmico. O primeiro custo é um custo de sincronização. Com um esquema dinâmico, cada thread deve ir ao sistema de execução após cada iteração, ou bloco de iterações, e pedir outra iteração a ser executada. O sistema deve ter o cuidado de distribuir as diferentes iterações para cada processador. O que requer sincronização entre os processadores. O tamanho do bloco de iterações deve ser grande o suficiente para minimizar a sincronização e também pequeno o suficiente para 41
58 preservar o balanceamento de carga. O segundo custo é a localidade dos dados. A localização das referências dos dados pode ser um problema dependendo do algoritmo (CHANDRA et al., 2001). Portanto, localidade e sincronização referem-se ao custo para comunicar as informações entre diferentes processadores no sistema. Em modernas máquinas baseadas em cache, localidade é muitas vezes o fator mais crítico que afeta o desempenho. Caches fornecem uma maneira de explorar localidade para garantir que um percentual muito maior de suas referências de memória reside numa memória mais rápida. Toda informação é mantida na memória principal (maior e mais lenta). Sempre que o sistema traz uma referência de memória no processador, ele armazena uma cópia dos dados na memória cache (menor e mais rápida). Antes de executar uma referência de memória, o sistema verifica se os dados estão dentro da cache. Se os dados são encontrados, o sistema não vai para a memória, ele apenas recupera a cópia dos dados encontrados na cache. Somente quando os dados não estão na cache, o sistema vai para a memória. Uma vez que a cache é menor do que a memória, ela não pode conter uma cópia de todos os dados. Em outras palavras, a cache pode ficar cheia, e, em tais casos, a cache deve remover alguns outros dados, a fim de abrir espaço para os novos dados (CHANDRA et al., 2001). Sempre que o usuário escreve alguns dados, o sistema tem duas opções. Em uma cache de gravação direta, os dados são gravados imediatamente de volta na memória. Em tal sistema, memória e cache são sempre consistentes; a cache sempre contém os mesmos dados encontrados na memória. Caches de gravação direta não são tão ruins como parecem. O cálculo não depende da gravação estar completa, assim o sistema pode continuar a calcular enquanto a gravação na memória está ocorrendo. Por outro lado, caches de gravação direta precisam transferir grandes quantidades de dados do processador para a memória e isso aumenta o overhead do sistema e torna mais difícil carregar outros dados da memória simultaneamente (CHANDRA et al., 2001). 42
59 A alternativa para uma cache de gravação direta é uma cache de gravação posterior (write-back cache). Nestas caches, o sistema não grava os dados na memória imediatamente e a cache não é mantida consistente com a memória. Em vez disso, um bit é adicionado a cada entrada na cache indicando se a memória está diferente do valor na memória principal. Quando o sistema retira uma entrada da cache, ele verifica o bit. Se ele indicar que está diferente, a memória principal é atualizada. A vantagem desta cache é que um processador pode potencialmente escrever na mesma localização várias vezes antes de ter que escrever um valor de volta na memória (CHANDRA et al., 2001). A ação de sincronização pode ser um fator de decréscimo da eficiência do programa, uma vez que alguns processadores podem ficar inativos, esperando pelo término de outros processos. Dois tipos de sincronização devem ser considerados: barreiras e exclusão mútua. Barreiras são usadas como um ponto global de sincronização. Um uso típico de barreiras é ao final de cada loop ou região paralela. Isso permite o usuário considerar uma região paralela como uma unidade isolada e não tem que considerar as dependências entre uma região paralela e outra ou entre uma região paralela e o código serial que vem antes ou depois da região paralela. Barreiras são muito convenientes, mas podem ser muito caras. Se loops ou regiões muito pequenas estão sendo paralelizadas, o tempo da barreira pode ser bastante significativo. O tempo para a barreira real não é o único custo para o uso de barreira. Barreiras sincronizam todos os processadores. Se houver algum desequilíbrio de carga e alguns processadores atingirem a barreira mais tarde do que outros, todos têm que esperar os lentos. Em alguns códigos, este tempo pode ser o efeito dominante (CHANDRA et al., 2001). A exclusão mútua cuida da consistência dos dados. Se vários processadores inserirem ou atualizarem dados em diferentes endereços de memória, não haverá problemas de inconsistência, porém será um problema se mais de um processador tentar atualizar os mesmos dados ao mesmo tempo, pois um deles pode se perder e com isso, gerar inconsistência (CHANDRA et al., 2001). 43
60 CAPÍTULO 3 CÓDIGOS DE SIMULAÇÃO COMPUTACIONAL CINÉTICA DE PARTÍCULAS A simulação computacional de plasmas compreende duas áreas gerais baseadas na descrição cinética e de fluidos (FIGURA 21). Enquanto a simulação de fluidos é feita através da solução numérica das equações magneto-hidrodinâmicas de um plasma (MHD), assumindo coeficientes de transporte aproximados, a simulação cinética considera modelos mais detalhados do plasma, envolvendo interações das partículas através do campo eletromagnético. Isto é conseguido tanto através da solução numérica das equações cinéticas do plasma (por exemplo, equações de Vlasov ou Fokker-Planck) como através da simulação de "partícula", em que se calcula os movimentos de uma coleção de partículas carregadas, interagindo umas com as outras e com campos aplicados externamente (BIRDSALL; LANGDON, 2005). As simulações de partículas permitem a interpretação de efeitos não lineares, como, por exemplo, instabilidades de ondas, difusão, aquecimento e aceleração de partículas em plasmas espaciais (SIMÕES, 2008). Os trabalhos pioneiros de Dawson e outros, no início dos anos 60, mostraram que, quando são usados métodos apropriados, sistemas relativamente pequenos, de alguns milhares de partículas, podem realmente simular com precisão o comportamento coletivo dos plasmas reais. Desde então, o desenvolvimento de 44
61 novos algoritmos e da disponibilidade de computadores mais poderosos tem permitido o progresso da simulação de partículas, desde em configurações simples, unidimensionais, eletrostáticas, a situações mais complexas e realistas, envolvendo campos eletromagnéticos em múltiplas dimensões e até 10 6 partículas (BIRDSALL; LANGDON, 2005). FIGURA 21 Classificação dos modelos de simulação computacional para plasma. Descrição Cinética Descrição de Fluido Códigos de Vlasov e Fokker-Plank Códigos de Partículas Códigos Híbridos Códigos MHD Fonte: Adaptada de Birdsall, Langdon, A simulação cinética tem sido particularmente bem sucedida em lidar com problemas básicos de física, em que as distribuições de partículas se afastam significativamente de uma distribuição Maxwelliana, como quando ocorrem ressonâncias onda-partícula, aprisionamento de partículas, ou aquecimento estocástico (BIRDSALL; LANGDON, 2005). Os modelos de simulação cinética via partículas podem ser uni, bi ou tridimensionais, eletrostáticos, magnetostáticos ou eletromagnéticos, dependendo do tipo de sistema estudado e dos diagnósticos necessários para a compreensão do fenômeno. Os resultados obtidos podem ser comparados com os resultados experimentais e devem estar de acordo com a teoria, podendo ainda prever comportamentos em novos experimentos (SIMÕES, 2008). Geralmente, estes modelos seguem um esquema onde primeiro as condições físicas do sistema são determinadas, tais como, as condições iniciais, as condições de contorno, a geometria, os tipos de partículas (íons ou elétrons), e o tipo de campo (eletrostático ou eletromagnético). A seguir, utilizando as equações de Maxwell e conhecendo as posições de todas as partículas e suas velocidades, são realizados os cálculos dos campos; as forças sobre as partículas são encontradas usando os campos elétricos e magnéticos na equação de movimento de Newton-Lorentz. 45
62 Então, são calculados os campos da carga inicial e densidades de corrente. Em seguida, movem-se as partículas (distâncias pequenas) e recalculam-se os campos devido às partículas estarem em suas novas posições e velocidades. É necessário levar em conta os campos externos e os campos gerados pelo movimento das próprias partículas carregadas. Este processo ocorre num pequeno intervalo de tempo, ou passo temporal, t, e é repetido tantas vezes quanto necessário (MARQUES, 2008; SIMÕES, 2008). A FIGURA 22 mostra os passos básicos na configuração de uma simulação cinética via partículas, o ciclo de avanço no tempo ( t) e os diagnósticos após os cálculos para serem analisados. FIGURA 22 Esquema de uma simulação cinética via partículas. Fonte: Adaptada de Simões, Pode-se afirmar então que o método de simulação por partículas consiste em acompanhar um grande número de partículas carregadas movendo-se sob a ação de forças (ou campos) produzidas pelo próprio movimento das partículas, resultantes da interação entre as mesmas, e/ou campos externamente aplicados (MORAES, 1999). Este método, conhecido como método PIC (Particle in Cell Partícula em Célula) posteriormente foi combinado ao método de colisões MCC (Monte Carlo Collision Colisões de Monte Carlo), aumentando, com isso, a acuidade de suas simulações. A FIGURA 23 mostra com mais detalhes as tarefas realizadas em cada 46
63 intervalo de tempo da execução do método PIC/MCC. No início de cada iteração, a força ( ) sobre cada partícula é calculada levando-se em conta os valores dos campos elétrico ( ) e magnético ( ) no ponto da grade (número finitos de pontos da região de interesse, que são discretizados no espaço físico) onde está a mesma, para que se possa então avançar sua posição ( ) e sua velocidade ( ) através das equações de movimento que seriam utilizadas em partículas reais (FIGURA 23a). Verifica-se então quais partículas atingiram as condições de limite, ou seja, se elas devem ser absorvidas, refletidas, ou combinadas, gerando novas partículas (FIGURA 23b). É chamado então o algoritmo de colisão MCC (FIGURA 23c), que irá definir os resultados das colisões através da geração de números aleatórios e tabelas de valores de seções de choque. A localização e velocidade das partículas que permanecem no sistema são utilizadas para se calcular, através de interpolação, as densidades de carga ( ) e corrente elétrica ( ) na grade (FIGURA 23d), e, com estas grandezas, através das Equações de Maxwell, calculam-se as alterações nos campos e em cada ponto da mesma, e, consequentemente a força ( ) que atuará sobre as partículas no próximo intervalo (FIGURA 23e). Este procedimento é repetido por vários passos no tempo (VAHEDI et al., 1993; VERBONCOEUR, 2005). FIGURA 23 Esquema de um ciclo do método PIC/MCC. Fonte: Adaptada de Vahedi et al., A Equação que rege o movimento é a de Newton-Lorentz (CHEN, 1985): dv m dt E v B, q (10) 47
64 d x v. (11) dt Os campos elétrico e magnético autoconsistentes são obtidos a partir das densidades de carga e corrente elétrica através das equações de Poisson e de Maxwell (CHEN, 1985; BIRDSALL; LANGDON, 2005): E, (12) 0 B 0, (13) B E, (14) t E B J 0. t (15) 0 Onde 0 é a permissividade elétrica. O método de leap-frog é utilizado para avançar os valores dos campos (E e B) e das partículas (posição x, velocidade v, e a densidade de corrente J) no tempo, conforme mostrado na FIGURA 24. O passo temporal t deve ser escolhido de forma que seja pequeno o suficiente para que seja possível observar as variações dos fenômenos estudados, ω p t << 1, onde ω p é a frequência local do plasma, e que exista estabilidade numérica durante a simulação. A condição de Courant- Fredericks-Lewy (CFL) evita a instabilidade numérica e é dada por x > v max t, (16) onde x é o espaçamento da grade e v max a velocidade máxima que as partículas do sistema podem adquirir. Esta condição garante que em um passo temporal a distância percorrida pelas partículas com velocidade v max não será maior que x. (BIRDSALL; LANGDON, 2005; SIMÕES, 2008; ZHOU et al., 2009). 48
65 FIGURA 24 Esquema do método leapfrog. Fonte: Zhou, et al., Como a quantidade de partículas reais é muito grande, foi criado o conceito de superpartícula, que representa muitas partículas de um plasma real com tamanho finito, com sua carga distribuída sobre uma região finita do espaço (SIMÕES, 2008). O número de superpartículas na simulação é encontrado usando initn area length N, (17) npf onde initn é a densidade inicial das espécies físicas no sistema [m 3 ]; area é a área do eletrodo [m 2 ]; length é o comprimento do sistema (distância entre os eletrodos) [m]; npf é o número de partículas físicas por partícula de computador. Por exemplo, para initn = 1e 15 ; area = 0,01; length = 0,3 e npf = e 7, o número de super partículas N = As superpartículas são colocadas em uma grade espacial, que representa o espaço físico onde ocorre o experimento (FIGURA 25). O espaçamento da grade, x (dimensão da célula) para uma simulação unidimensional, deve ser pequeno quando comparado com o menor comprimento de onda de interesse, k x << 1. Normalmente, x varia de um a três comprimentos de Debye (BIRDSALL; 49
66 LANGDON, 2005), se for maior que três comprimentos de Debye surgirá instabilidade numérica (VAHEDI et al., 1993; SIMÕES et al., 2011). O comprimento de Debye proporciona a medida da distância na qual a influência do campo elétrico de uma partícula individual é sentida pela outra partícula carregada dentro do plasma. O resultado é uma densidade adicional de carga espacial negativa (ou positiva) que cancela o efeito da carga inicial a distâncias maiores em relação ao comprimento característico de Debye dado por: kt 0 D, (18) 2 nee onde T é a temperatura, n e é a densidade dos elétrons, e é a carga do elétron, ε 0 é a permissividade do vácuo e k é a constante de Boltzmann (BIRDSALL; LANGDON, 2005). FIGURA 25 Grade numérica onde as super-partículas ( campos elétricos e campos magnéticos (símbolos e Δ). ) interagem entre si através de Fonte: Outro fator importante é o número de partículas por ponto na grade, quanto maior o número de partícula por ponto na grade, menor serão as flutuações numéricas relacionadas ao cálculo dos campos eletromagnéticos (BIRDSALL; LANGDON, 2005). A largura da célula é calculada usando length x, (19) nc 50
67 onde nc é o número de células espaciais, ou seja, o tamanho da grade. Por exemplo, para length = 0,3 e nc = 100, x = 0,003. É sobre a grade que são feitos os cálculos dos campos elétricos e magnéticos e das posições e velocidades das partículas. A grade é discretizada e os valores dos campos só são conhecidos em cada um de seus pontos. Dessa forma, se uma partícula encontra-se entre dois desses pontos, o valor do campo é calculado através da interpolação dos valores nos dois pontos vizinhos (VAHEDI et al., 1993). O modelo unidimensional pode ser considerado como um grande número de células de partículas carregadas movendo-se sob a ação de um campo elétrico, direcionado ao longo do eixo x, externamente aplicado e dos campos internos autoconsistentes; não existe variação nas direções y ou z. Os processos de colisão utilizados no modelo PIC/MCC para o argônio, por exemplo, considerando quatro espécies de partículas (argônio atômico, íons de argônio ionizados, elétrons e átomos metaestáveis) (ROBERTO; SMITH; VERBONCOEUR, 2003; CIZZOTO et al., 2002), são: e + Ar e + Ar (Espalhamento Elástico) (20) e + Ar e + Ar * (Excitação [11,83 ev]) (21) e + Ar e + Ar m (Excitação Metaestável [11,55 ev]) (22) e + Ar 2e + Ar + (Ionização [15,76 ev]) (23) e + Ar m 2e + Ar + (Ionização Metaestável [4,21 ev]) (24) Ar m + Ar m Ar + + Ar + e (Ionização a partir de Metaestáveis) (25) Ar m + e Ar r + e (Mudança de Metaestável para nível ressonante) (26) Ar + + Ar Ar + Ar + (Troca de Carga) (27) Ar + + Ar Ar + + Ar (Espalhamento Elástico) (28) 51
68 3.1. Abordagens para paralelização de códigos PIC Existem diferentes abordagens para paralelizar um código PIC, mas uma primeira divisão envolve duas abordagens básicas do particionamento da carga computacional. Uma é pela divisão das grades numéricas, que contém a densidade das partículas e dos campos eletromagnéticos, caracterizada por uma separação por regiões espaciais (FIGURA 26a); outra é pela divisão com base nas partículas sobre a quais são realizados os cálculos das posições e velocidades das mesmas, decompondo-se o domínio em termos do índice da partícula no vetor, independente da posição no espaço (FIGURA 26b). Em cada passo de tempo, informações de campos e densidade das partículas são trocadas entre os processadores. Como as partículas estão em constante movimento, no caso da divisão espacial elas podem sair do domínio de um processador e ir para outro, com isso haverá comunicação e um desbalanceamento de carga, que deve ser tratado a cada n ciclos. No outro caso, a cada ciclo as posições das partículas dos diferentes processos devem ser comunicadas, para checagem de eventuais colisões, o que envolve comunicação e o desbalanceamento pode ocorrer como resultado das colisões, reemissões e outros efeitos ocorrendo de forma desigual (o que também pode ocorrer com a outra abordagem). FIGURA 26 Decomposição de domínio em regiões espaciais (a) e decomposição de domínio pelo índice das partículas (b). Uma estratégia para paralelizar programas PIC é dividir a quantidade de partículas e de pontos nodais entre os processadores no início da simulação, e cada processador realiza todas as operações do código, e possui uma cópia de todas as variáveis envolvidas, não havendo migração de partículas ou de pontos nodais entre os processadores. Esta estratégia é conhecida como decomposição estática para 52
69 partículas e campos (LUBECK; FABER, 1988). Sua vantagem é que o balanceamento de carga é sempre mantido, sem esforço adicional de comunicação entre os processadores, e sua desvantagem é a replicação das informações na memória. Liewer e Decyk (1989) propuseram um balanceamento dinâmico de carga que foi implementado em um código PIC eletromagnético unidimensional usando um método que adiciona uma sobrecarga muito pequena para o código paralelo. O código foi implementado em paralelo usando o algoritmo GCPIC (General Concurrent PIC) em que as partículas são divididas entre os processadores particionando o domínio espacial. Partições são criadas dinamicamente durante a execução de modo que os subdomínios têm aproximadamente os mesmos números de partículas. As partições da grade são calculadas a partir de um perfil aproximado da densidade do plasma, em vez de a partir dos dados das partículas, fazendo com que os cálculos dos limites dos novos subdomínios sejam rápidos e simples. Para todos os casos executados, a eficiência do código paralelo sempre melhora quando o balanceamento de carga dinâmico é usado. Para o caso de teste apresentado na publicação, o tempo de execução foi de 1,8 vezes mais longo quando o balanceamento dinâmico de carga não foi utilizado. Outra abordagem utilizada é dividir apenas a quantidade de pontos nodais de campo entre os processadores. Esta estratégia diminui a quantidade de informação replicada e o uso de memória, porém, aumenta a comunicação entre os processadores, pois quando as partículas migram de uma região para outra, a interpolação dos valores de campo (efetuada pelo processador encarregado destas partículas) passa a envolver valores nodais que podem estar distribuídos na memória de outros processadores (WALKER, 1989; MARQUES, 2008). Outra proposta envolve a decomposição de domínio. Os subdomínios contêm o mesmo número de partículas e são distribuídos entre os processadores. Da mesma forma, os pontos nodais são distribuídos entre os processadores. No decorrer da simulação, as partículas podem sair ou entrar no subdomínio de outro processador, e a densidade do número de partículas pode mudar sensivelmente, ocorrendo então 53
70 um desbalanceamento de carga, sendo necessário refazê-lo através de um algoritmo de balanceamento dinâmico (FERRARO; LIEWER; DECYK, 1993) otimizado. Esta estratégia foi testada com cerca de 162 milhões de partículas (DECYK, 1995), e verificou-se que o tempo de cálculo dos campos é muito pequeno em relação ao tempo de cálculo total em cada iteração. Logo, pode-se usar um algoritmo de balanceamento mais simples. Uma revisão destas estratégias é encontrada em Carmona e Chandler (1997). Para uma grande classe de simulações de plasma, uma decomposição espacial estática de partículas, adequadamente escolhida, pode ser tão eficiente quanto a abordagem com balanceamento dinâmico, com a vantagem de ter menor complexidade implementacional (MARQUES, 2008, p. 57). Uma estratégia para balanceamento dinâmico de carga para o algoritmo paralelo desenvolvido por Ferraro, Liewer e Decyk em 1993, é definir grupos de células em subdomínios com excesso de partículas. As instruções relacionadas às partículas que estão nestes grupos são atribuídas uma a uma aos demais processadores com o intuito de restabelecer o balanço de carga (PLIMPTON et al., 2003). O gerenciamento desses grupos pode se tornar bastante complexo, pois além de novos grupos serem criados, quando uma partícula sai do subdomínio de um processador e consequentemente de um grupo, tem que ser determinado qual processador será encarregado do subdomínio para o qual a partícula migrou e para qual grupo ela vai ou se será necessário criar um novo grupo. Shon et al. (2001) propuseram um método para aumentar a velocidade do código de simulação PIC uni e bidimensional (XPDP1 e XPDP2, respectivamente), através da redução do número de partículas durante a execução. Partículas de mesma espécie e bem próximas, e que estão dentro de uma mesma célula, são combinadas em uma partícula que tem maior carga, mantendo as leis de conservação de posição e densidade de carga. A energia é conservada pela divisão do espaço de fase das partículas em cada célula em vários segmentos pequenos pela magnitude e direção da velocidade, e pela fusão das partículas que tenham energias mais próximas no mesmo segmento do espaço de fase. Segundo os 54
71 autores, este método melhora a estabilidade do código, além de reduzir o tempo de processamento. Wolfheimer et al. (2006) propuseram duas estratégias de paralelização. A primeira é baseada na decomposição geométrica do domínio computacional (particionamento) entre os nós do computador. Cada nó é responsável por executar tarefas computacionais sobre os field DOFs (field degrees of freedom, graus de liberdade de campo) e partículas computacionais contidos no respectivo subdomínio (partição). A vantagem desta estratégia decorre do fato de que as operações sobre as partículas não requerem a comunicação entre processos e, consequentemente, eles não apresentam nenhuma sobrecarga de comunicação. No entanto, como a distribuição de partículas muda durante a simulação, os campos que impulsionam as partículas vão se tornar desequilibrados. Isto não apenas deteriora o desempenho do algoritmo paralelo, mas, adicionalmente, conduz à falha do cálculo. Entretanto, algumas partículas saem do subdomínio associado ao seu processo e migram para outro processo e, portanto, a comunicação entre processos aumenta. Uma possibilidade para melhorar o desempenho é alterar a partição do domínio computacional de acordo com a distribuição de partículas. Enquanto isto pode melhorar significativamente o equilíbrio da carga de trabalho computacional, também aumenta a comunicação entre processos devido à troca de dados que ocorre durante a operação de balanceamento de carga. Em alguns casos este custo adicional, ainda compensa o benefício de um melhor balanceamento de carga. A segunda estratégia atribui as partículas computacionais aos processos independentemente de suas posições no domínio computacional. A vantagem desta estratégia é o inerente balanceamento da carga de trabalho, tanto para calcular os campos quanto para movimentar as partículas. No entanto, como as partículas são atribuídas aos processos arbitrariamente, elas podem estar localizadas em uma célula para a qual um determinado processo não mantém as informações necessárias dos field DOFs, e elas precisam ser enviadas para este processo. Assim, esta abordagem fornece um balanceamento da carga de trabalho, aumentando os custos de comunicação. Outros algoritmos têm sido propostos que tentam combinar os pontos fortes de ambos os esquemas. 55
72 No entender de Wu et al. (2007), existem muito poucos estudos em processamento paralelo do método PIC utilizando a decomposição de domínio dinâmico, que é importante para o método baseado em partícula alcançar melhor balanceamento de carga. Os dois melhores exemplos na literatura, segundo os autores, são os estudos realizados por Seidel et al. (2002) e Liewer e Decyk (1989). Nestes estudos, decomposições de domínio para partículas e para os campos são diferentes, o que requer intensiva comunicação em cada passo de tempo. Para Decyk e Nortonb, citado por Marques (2008, p. 60), O número de possíveis combinações entre estratégias e otimizações de paralelização de simulações PIC é considerável. Além disso, não existe uma regra geral; cada simulação particular que executará em uma dada arquitetura e com especificado recurso computacional tem características e limitações que devem ser exploradas convenientemente na busca de melhor eficiência. Neste trabalho, nas seções e , mostramos que a abordagem utilizada é a divisão por índice de partículas, com balanceamento dinâmico O código eletrostático unidimensional XPDP1 XPDP1 (X Plasma Device Planar 1-Dimensional) é um código computacional executado em plataformas Unix com X-Windows e em PC's com emuladores de X- Windows, utilizando para isso o método PIC/MCC (Plasma Theory and Simulation Group, 1993). Ele simula um plasma contido entre dois eletrodos conectados por um circuito externo. Este circuito inclui resistência (R), indutância (L) e capacitância (C), e também possui fontes de corrente e voltagem, como mostra a FIGURA 27. O XPDP1 foi desenvolvido pelo Grupo de Teoria e Simulação do Plasma da Universidade da Califórnia em Berkeley (<http://langmuir.eecs.berkeley.edu/pub/ codes/xpdp1>), em 1993, na linguagem C. Um detalhamento histórico da evolução do programa até seu presente estado pode ser encontrado em XPDP1 (1993), que é o manual escrito por seus desenvolvedores, e que foi utilizado como fonte para a maior parte das informações expostas nesta seção (MORAES, 1999; XPDP1, 1993). 56
73 FIGURA 27 Esquema de um circuito RLC em série e fonte de voltagem/corrente, para o modelo unidimensional XPDP1, onde considera-se o movimento das partículas na direção x. Fonte: Adaptada de O XPDP1 usa a biblioteca gráfica XGrafix, também desenvolvida em Berkeley, que é um ambiente de janelas para a visualização interativa de quaisquer simulações de fenômenos físicos (WONG, 1999). É esta biblioteca que controla a execução e visualização da simulação, e também cria e atualiza as janelas de diagnósticos (FIGURA 28). O XPDP1, propriamente dito, é responsável pelos cálculos da evolução física do problema, e por fornecer ao XGrafix as variáveis a serem plotadas. As características do plasma, como partículas e campos eletrostáticos, são especificadas pelo usuário em tempo de execução usando um arquivo de entrada. Como a função responsável pelo controle dos cálculos dos movimentos, colisões, ajustes, entre outros, executa apenas uma iteração, o XPDP1 passa o controle da simulação para o XGrafix, que, por sua vez, chama repetidamente esta função, tornando possível acompanhar a evolução do modelo ao longo do tempo. A simulação, então, prossegue, com saídas gráficas de vários diagnósticos especificados pelo usuário, que são atualizados a cada passo no tempo (pode-se escolher que a alteração do gráfico ocorra num número maior de ciclos). O usuário pode também guardar o estado da simulação em um determinado momento, em um arquivo no disco rígido, permitindo que em algum outro momento, mais tarde, 57
74 a execução e a visualização dos diagnósticos possam ser retomadas a partir daquele ponto (XPDP1, 1993), mas não está implementada a possibilidade de apenas visualização a partir de uma seqüência de estados estocados em disco. FIGURA 28 Janelas de execução do XGrafix/XPDP1. (a) Painel de Controle; (b) Lista de janelas de diagnóstico que podem ser visualizadas; (c) e (d) exemplos de diagnósticos. (a) (b) (c) (d) Como critérios de parada, o usuário pode especificar um número máximo de iterações, na linha de comando de execução, ou, interromper a simulação a partir do momento em que o modelo entra em estado de equilíbrio. Isso ocorre quando a taxa de perda de partículas se iguala à taxa de criação das mesmas, e quando a quantidade de energia depositada no sistema se iguala à quantidade perdida pelo mesmo (VAHEDI et al., 1993) Análise do funcionamento do sistema O código do XPDP1, versão 4.11, está organizado em 18 (dezoito) arquivos fontes codificados na linguagem C, cada um contendo uma determinada quantidade de funções, e 2 (dois) arquivos de cabeçalho. A FIGURA 29 mostra o fluxo simplificado de execução do XPDP1 com o XGrafix habilitado, e com o gás argônio para compor o plasma (também podem ser: hélio, oxigênio ou neon), para um ciclo de execução. O código do XGrafix, versão , está organizado em 17 (dezessete) arquivos fontes codificados na linguagem C, cada um contendo uma determinada quantidade de funções, e 8 (oito) arquivos de cabeçalho. 58
75 As funções XGInit, XGInitX, XGInitTclTk e XGStart são funções do XGrafix chamadas pelo XPDP1. FIGURA 29 Fluxo simplificado de execução do XPDP1 com o XGrafix habilitado (1 ciclo). A FIGURA 30 mostra o fluxo simplificado de execução do XPDP1 com o XGrafix desabilitado, para um ciclo de execução. Podemos observar que todas as funções que estão envolvidas com a parte gráfica do sistema, janelas de diagnósticos, são desabilitadas e, com isso, o esforço computacional é bem menor. Para termos uma visão geral do sistema e seu funcionamento, o Anexo A consta de uma breve descrição das funções dos arquivos fontes e dos arquivos de 59
76 cabeçalho do XPDP1 original (como disponibilizado pelos pesquisadores de Berkeley) (<http://langmuir.eecs.berkeley.edu/pub/codes/xpdp1>). FIGURA 30 Fluxo simplificado de execução do XPDP1 com o XGrafix desabilitado (1 ciclo). O XPDP1 utiliza vetores e matrizes para armazenar os dados envolvidos no sistema, como as posições das partículas na grade (matriz x, onde cada linha da matriz representa uma espécie), as velocidades das partículas (matrizes vx, vy e vz), a grade onde são realizados os cálculos dos campos eletromagnéticos (matriz sp_n e vetor xgrid). A matriz x armazena a posição de cada partícula na grade através de números em ponto flutuante. A parte inteira de cada número significa em que célula da grade a partícula está, enquanto a parte decimal significa o deslocamento relativo da partícula dentro da célula. Por exemplo, uma partícula com posição 3,728 está 60