O modelo de componentes Hash junta-se aos outros modelos de componentes voltados a aplicações de CAD com uma proposta adicional: conceder aos componentes uma natureza intrinsecamente paralela [20].
3.5. O Modelo de Componentes Hash 40
Na programação paralela, os interesses de uma aplicação devem estar implementados de forma distribuída entre os processos que formam o programa paralelo. Porém, uma vez que a programação paralela está concentrada na decomposição do programa em processos [19], ao invés dos interesses, há a tendência natural de tratar processos como unidades dominantes da decomposição do software, a qual julgamos errônea. Na prática, em uma plataforma de componentes, essa limitação implica que uma instância de um componente realizará a sua execução apenas em uma única unidade de processamento, encapsulada em um processo. Assim, um interesse que deveria estar encapsulado em uma única unidade de decomposição do programa, como convém a boa prática de modularização de programas na engenharia de software, estaria espalhado em um conjunto de componentes responsáveis por implementar o interesse.
Esse problema é amenizado quando o paralelismo da plataforma de componentes é implementado por meio do paradigma SCMD ( do inglês single component, multiple data), onde há a necessidade de um único componente que é instanciado em um conjunto de unidades de processamento, pois o interesse estaria encapsulado nesse componente. Porém, em algumas plataformas de componentes, como o framework CCAffeine, as instâncias de componentes comunicam-se na execução paralela por meio de passagem de mensagens usando alguma biblioteca padrão, como o MPI, quando deveriam comunicar-se somente através de suas interfaces regulares (portas uses e provides), conforme suposto pelo modelo de componentes. Nesse caso, há uma quebra do encapsulamento do componente tendo em vista a existência de comunicações clandestinas entre os componentes, as quais ocorrem sem que a plataforma esteja ciente. Para garantir a regularidade das comunicações, seria recomendável, do nosso ponto de vista, introduzir no modelo novos tipos de portas entre os componentes, que permitam a comunicação par-a-par entre um conjunto de instâncias de componentes paralelos que desejam realizar uma computação paralela. Porém, isso não resolveria o problema do encapsulamento do interesse, caso tais instâncias sejam de componentes distintos, o que seria necessário para o padrões MPMD (do inglês multiple program, multiple data) de interação entre processos.
A proposta do modelo Hash é eliminar essa limitação, possibilitando que os interesses sejam encapsulados em uma unidade de programa a despeito da sua implementação em várias unidades de processamento distribuídas e suportando programação MPMD. O modelo parte do pressuposto de que processos e interesses são conceitos ortogonais [19]. Assim, um componente do modelo Hash, também
conhecido como componente #, pode conter partes que executam em unidades de processamento distintas. A essas partes, atribuímos o nome de unidades.
Um sistema de programação baseado em composição hierárquica de componentes é compatível com o modelo Hash se possui as seguintes características:
◮ componentes são formados por partes, chamadas unidades, que podem ser multiplamente instanciadas em unidades de processamento distintas de um computador paralelo de memória distribuída;
◮ componentes podem ser compostos hierarquicamente por sobreposição, gerando novos componentes;
◮ suporta um conjunto de espécies de componentes, de tal forma que cada componente pertence a uma espécie;
Portanto, um único componente # executa distribuidamente em várias unidades de processamento, através de suas unidades. Na instanciação de um componente #, várias instâncias de uma unidade podem existir localizadas em unidades distintas de processamento. São essas unidades que tornam o componente intrinsecamente paralelo. É responsabilidade da plataforma oferecer uma visão consistente do componente #, o qual deve ser visto de forma indivisível.
3.5.1 Sobreposição de Componentes #
A sobreposição [19] concede ao modelo a capacidade de criação de componentes a partir de outros componentes de forma hierárquica, similar ao que se tem no modelo Fractal, porém adaptado às necessidades de um componente intrinsecamente paralelo.
Para melhor compreensão desse conceito, juntamente com os conceitos de unidade, componente aninhado, fatia e ação, iremos fazer uso de um exemplo. Suponhamos que se deseje escrever uma aplicação paralela para executar sobre um cluster de 4 nós. O processamento será realizado através da coordenação de dois componentes, os quais aplicam seus algoritmos sobre uma matriz. Assim, nessa solução, teremos quatro componentes envolvidos: os três já citados (a estrutura de dados matriz também é um componente) e um novo componente descrito como uma composição dos anteriores que tem o papel de coordenar a execução. A Figura 3.1 apresenta um diagrama, onde as elipses representam os componentes #. Componentes inscritos a outros representam componentes aninhados. Por exemplo, os componentes CalculaX, CalculaY e Matriz são componentes aninhados de
3.5. O Modelo de Componentes Hash 42
Resolvedor. Como implicação, Resolvedor é um componente definido por sobreposição de CalculaX, CalculaY e Matriz. Os retângulos representam unidades. Portanto, CalculaXpossui 4 unidades, simbolizadas pelos retângulos no interior da elipse que o representa.
Figura 3.1: Representação de um componente #
Fonte: Próprio autor.
As unidades também podem ser compostas pelas unidades de componentes aninhados. Nessa relação, representada no diagrama por uma seta, as unidades constituintes são chamadas de fatias da unidade composta. No nosso exemplo, a unidade x1 do componente CalculaX, a unidade y1 do componente CalculaY e ainda a unidade m1 do componente Matriz são fatias de uma das unidades do componente Resolvedor. Como pode ser visto, esta mesma relação é mantida entre as demais unidades dos componentes.
A unidade é a menor parte de decomposição de um componente #. Assim, supondo a execução deste componente no citado cluster de 4 nós, cada uma das unidades xn será implantada em um nó distinto da máquina, apesar de estarem presentes no mesmo componente. Este é conceito de componente paralelo: um único componente, executando distribuidamente em vários nós. Não se trata de um cópia do componente, mas sim fragmentos que, inclusive, podem ser diferentes. Por exemplo, as computações presentes em x1 podem ser distintas das definidas pelos algoritmos da unidade x2.
algoritmos em suas unidades através de ações. Fazendo uma analogia com a programação orientada a objetos, ações são similares a métodos. Ao se definir uma nova ação em uma unidade, pode-se fazer uso das ações de suas fatias. Por exemplo, as unidades do componente Resolvedor podem fazer uso das ações definidas nas suas fatias xn e yn. Na prática, a unidade e suas fatias serão implantadas no mesmo nó de processamento.
Unidades também podem definir condições, cujo papel é descrever computações que forneçam um resultado booleano. Essas computações servem para simples verificação de estados da aplicação, não devendo ser usadas para processamento útil.
3.5.2 Espécies de Componentes
As espécies classificam os componentes quanto ao seu papel na aplicação, permitindo que a plataforma os trate de forma diferente, adaptando-se a diferentes modelos de conexão e implantação, bem como modelos de ciclo de vida, que sejam necessários dentro de um domínio de aplicação.
Nas plataformas de componentes tradicionais, define-se uma única espécie de componentes e um conjunto fixo de conectores entre estes, de forma que quando novas abstrações são necessárias para lidar com necessidades de novas aplicações dentro do domínio, é preciso estender o modelo. Em uma plataforma do modelo Hash, uma vez que componentes # podem estar associados a interesses funcionais ou não-funcionais, bem como concretos ou abstratos, basta introduzir-se na plataforma uma nova espécie de componente para tratar aquela nova abstração, bem como definir as regras da relação dos seus componentes com componentes das espécies já existentes.
Espécies de componentes podem também definir uma linguagem de composição de componentes dentro de um domínio, oferecendo suporte a desenvolvimento de aplicações pela combinação de partes, os componentes #, que representam abstrações dentro de domínios específicos.
Finalmente, como componentes # são intrinsicamente paralelos, podem representar conectores entre componentes paralelos. Dessa forma, uma plataforma compatível com o modelo Hash pode conter um conjunto evolutivo de conectores, de acordo com as necessidades dos computadores paralelos da tecnologia vigente.