• No results found

Aplicações com requisitos de Computação de Alto Desempenho (CAD) são frequen- temente desenvolvidas visando explorar detalhes das arquiteturas de computação paralela. Para isso, com base no conhecimento arquitetural, os desenvolvedores adotam técnicas eficientes que otimizam a utilização dos recursos, tais como unidades de processamento, memória (local/distri- buída), aceleradores computacionais (e.g. GPUs (FAN et al., 2004), MICs (DURAN; KLEMM, 2012) e FPGAs (HERBORDT et al., 2007)), bem como interação através de redes de comu- nicação. No entanto, a atual complexidade do software tem exigido um aprimoramento dessa abordagem, necessitando de ferramentas que propiciem maior produtividade no desenvolvimento de programas paralelos.

(NIELSEN, 2005), aplicações móveis e na Internet (FALOUTSOS et al., 1999) (e.g. motores de busca, redes sociais, aplicações georreferenciadas - GPS, etc), emergiram plataformas de computação para suprir a demanda por processamento eficiente de intensas massas de dados, o que resultou no sucesso de frameworks que implementam modelos como MapReduce e Pregel, tais como Spark, Giraph, GraphX1, dentre outros. Trata-se de um cenário em que boa parte desses frameworks buscam oferecer alto nível de abstração para o desenvolvimento das aplicações, eliminando a necessidade do desenvolvedor programar o paralelismo inerente. Vê-se que isso é diferente das práticas utilizadas nas aplicações legadas de CAD, onde predomina a programação estruturada, em linguagens como Fortran ou C, que possuem significativa expressividade de paralelismo, tendo apoio de ferramentas como as bibliotecas de passagem de mensagens (MPI), mas ainda possuindo baixo nível de abstração. Nos frameworks emergentes, significa que a preocupação com a arquitetura e com os detalhes da paralelização é potencialmente delegada aos próprios frameworks. Com isso, a parte complexa de paralelismo pode ser automaticamente realizada com a aplicação de suposições sobre a distribuição e processamento dos dados e das computações, tarefa comumente programada de forma manual em aplicações científicas legadas e atuais (CHAVARRÍA-MIRANDA et al., 2015; BAILEY, 1991).

O alto nível surgente nos frameworks modernos está mais próximo da engenharia de softwarecontemporânea, pois possibilita também o incremento da escala de desenvolvimento, requisito especialmente útil para a crescente complexidade do software de CAD. Porém, o encap- sulamento das técnicas de paralelismo nem sempre permite explorar o melhor das plataformas de execução, como ocorreu no caso dos algoritmos de escalonamento ineficientes para máquinas heterogêneas no Hadoop, onde Zaharia et al (ZAHARIA et al., 2008) propuseram um novo escalonador de tarefas. Além disso, existem algoritmos, por exemplo de particionamento e balanceamento de carga de grafos, sensíveis aos detalhes dos ambientes de execução, bem como sensíveis às técnicas de sincronização de mensagens (HARSHVARDHAN et al., 2014). Por exemplo, Xu et al, sobre partição e balanceamento de carga, demonstra a perda de desempenho quando há máquinas com diferentes capacidades, além de canais para operações de comunicação diferentes (XU et al., 2015). Nesse trabalho, foram experimentadas 26 máquinas com 3 delas diferentes das demais (menor capacidade), onde a remoção dessas máquinas diferentes resulta em aumento do desempenho, ou ainda, alternativamente, podem receber menos carga que as demais, mantendo o desempenho. De fato, algoritmos possuem perfis diversificados quanto aos requisitos

de computação distribuída, de forma que o ambiente de execução deve ser levado em conta para minimizar degenerações. Em grafos, por exemplo, alguns algoritmos (HARSHVARDHAN et al., 2014; XIE et al., 2015) possuem desempenho melhor ou pior de acordo com o caráter síncrono ou assíncrono do mecanismo de troca de mensagens, como discutido na Seção 3.7.

Identificar a melhor forma de execução em uma plataforma, bem como os requisitos de paralelismo para algoritmos particulares, não é uma tarefa simples se for feita de forma auto- matizada, conclusão já observada no lançamento do framework Giraph++ (TIAN et al., 2013), quando ofereceram ao utilizador a possibilidade de especificar a estratégia de particionamento. Nesse trabalho, o utilizador, ao definir sua estratégia, deve conhecer também a arquitetura, pois considerará ou não a existência de unidades de processamento heterogêneas, delegando mais ou menos carga segundo uma certa capacidade do hardware, caso assim considere vantajoso. Porém, há frameworks recentes (CHEN et al., 2017; XIE et al., 2015) que buscam suportar determinadas características ou técnicas automatizadas para paralelismo, onde seus resultados apontam sucesso para alguns algoritmos. Por exemplo, eles apostam em heurísticas para atingir modos híbridos em sincronismo/assincronismo, supondo quando um é melhor que o outro, bem como modos empurrar/puxar (push/pull) dos dados. Todavia, a ciência deve ainda examinar abordagens com propósito geral no processamento de grafos, onde há a possibilidade de equili- brar instruções automáticas encapsuladas no framework e a expressividade do desenvolvedor, o qual informa suas necessidades para o algoritmo em uma dada plataforma, com uma certa técnica de paralelismo. Com isso, características de computação (Seção 3.6.1), tais como modelo de programação, fases de execução, modo empurrar/puxar, modo de execução com sincronis- mo/assincronismo/híbrido, também podem ser generalizados, ou seja, personalizáveis. Por exemplo, se um algoritmo particionador A é eficiente para balancear carga de grafos em um conjunto de máquinas homogêneas H, esse mesmo algoritmo tem chances de não ser eficiente se o conjunto de máquinas for alterado para um conjunto de máquinas heterogêneas H′. Porém,

se A receber uma instrução dizendo qual o contexto do conjunto de máquinas alvo, A tem pelo menos a chance de recalcular suas suposições, podendo ainda ser eficiente. Em frameworks que adotam pipe-lines de MapReduce, sugerido por Condie et al (CONDIE et al., 2009), esse cenário de particionamento é crítico, especialmente para multitarefas escalonadas em um mesmo clustermulti-inquilino, ocupando concorrentemente recursos das máquinas, caracterizando a necessidade de balanceamento dinâmico de carga entre fases de processamento ou pipe-lines.

propostas para a plataforma HPC Shelf, discutida no Capítulo 4. Isso porque utiliza como pilar o desenvolvimento baseado em componentes Hash, no qual os componentes são desenvolvidos e selecionados por uma certa aplicação segundo suposições a respeito de um contexto de execução. Esse contexto, potencialmente genérico, é naturalmente expresso pelo desenvolvedor na criação das aplicações, o que é uma característica de alto nível que instrui a execução, onde características de plataformas e requisitos de aplicações são resolvidos por meio do elemento arquitetural Core. Um arcabouço para grafos grandes, em conformidade com o modelo de componentes Hash e a nuvem HPC Shelf, permite potencializar o propósito geral, pois possibilita que a contextualização defina a melhor estratégia para execução, que poderá ficar sujeita às instruções do especialista no domínio de grafos e da generalidade dos componentes disponibilizados pelo desenvolvedor especialista em computações paralelas.

Dessa forma, será introduzido neste capítulo o arcabouço Gust, que visa suportar o processamento de grafos em larga escala, aplicando a engenharia de software baseada em componentes às técnicas discutidas nos frameworks do Capítulo 3. Na Seção 5.3, discute- se como a estrutura de componentes é organizada para suprir os requisitos de grafos. Para isso, apresentam-se primeiramente os estudos envolvendo a implementação de um arcabouço MapReduce baseado em componentes paralelos do modelo Hash, que é voltado à plataforma HPC Shelf para computação paralela em larga escala. Alguns componentes Gust estendem componentes desse arcabouço, para permitir o funcionamento em ambiente distribuído. Portanto, após as definições do MapReduce, destacam-se arquitetura e propriedades do Gust.