As
bibliotecas de paralelização são a alma do desenvolvimento dos aplicativos para os clusters
Linux, pois são elas que possibilitam que um mesmo aplicativo utilize os recursos computacionais de mais de uma máquina ao mesmo tempo, através dos protocolos de comunicação.
O cerne das aplicações paralelas é a utilização de mais de um processador para rodar a mesma aplicação, para se obter isso, é necessários que esses processadores se comuniquem, o que ocorre basicamente de duas formas:
- através de memória compartilhada ou
- troca de mensagens.
A
memória compartilhada é utilizada quando existem mais de um processador em uma mesma máquina. Esse tipo de hardware é bastante comum em grandes CPDs. Para os usuários de máquinas pessoais e pequenas empresas, não é comum possuir mainboards com mais de dois processadores, devido ao seu alto custo. Dessa forma, esse tipo de paralelismo não é tão comum entre os usuários, embora seja uma programação relativamente fácil de ser feita. As máquinas com essa configuração gerenciam as requisições de acesso, feita pelos processadores, à uma memória unificada, impedindo com isso o acesso simultâneo de mais de um processador.
A
memória distribuída é utilizada quando se tem mais de uma máquina trabalhando em conjunto, ou seja, cada máquina é independente das outras, com processador e memória própria, além disso é necessário que elas troquem informações entre si, isso é feito via rede. É nesse contexto que entram em cena as bibliotecas de trocas de mensagens, permitindo que várias máquinas de baixo custo trabalhem com desempenho próximo a uma máquina de alto custo.
Com a evolução dos compiladores a divisão entre memória compartilhada e memória distribuída está ficando obsoleta, com as simulações de memória compartilhada em máquinas inicialmente com memória distribuída. A idéia consiste em os processadores através de rede e simular memória compartilhada através de troca de mensagens. Isso é feito com cada processador determinando uma área de sua memória que será compartilhada com os demais processadores da rede.
As bibliotecas de programação utilizadas para trabalhar com esses tipos de máquinas são:
OpenMP
O
OpenMP não é exatamente uma biblioteca de comunicação. Essa
biblioteca tem como objetivo prover a comunicação entre processadores com
memória compartilhada, ou em maquinas que simulem memória compartilhada em cima de memória distribuída.
O OpenMP divide as iterações entre os processadores disponíveis, isso implica que para um mesmo código existe trechos do código que rodam de forma seqüencial e trechos que rodam de forma paralela. Embora não seja um método que possibilite uma grande otimização do processamento, se comparado com os outros métodos de paralelismo, o OpenMP possui a vantagem de ser de fácil utilização, pois as diretivas são auto gerenciáveis.
PVM
A idéia do
Parallel Virtual Machine consiste em montar uma máquina virtual de n processadores e usá-los para executar tarefas simultâneas. O PVM é dividido em três partes principais:
- console: usado para montar a máquina paralela virtual.
- daemon: um programa que roda em cada máquina do ambiente estabelecendo a comunicação entre as diversas máquinas.
- biblioteca: é na biblioteca que reside as funções e sub-rotinas que instruem o código a dividir as tarefas entre os daemons.
A biblioteca dispõe de recursos que possibilitam manipular qualquer coisa do seu ambiente virtual, inclusive em tempo de execução, embora não seja muito inteligente fazê-lo dessa forma. Devido ao custo computacional de se adicionar e retirar máquinas em tempo de execução. O ideal é criar a máquina virtual fora do código, através do console, e usá-la várias vezes, ou mesmo deixá-la ativa enquanto as máquinas estiverem ligadas, além de possibilitar disparar e matar processos a partir do console.
MPI
O MPI (
Message Passing Interface) é constituído por um padrão de troca de mensagens com sintaxe definida, mas preservando características exclusivas de cada arquitetura, inclusive para arquiteturas de memória compartilhada.
O principal objetivo do MPI é otimizar a comunicação e aumentar o desempenho computacional das máquinas, não possuindo dessa forma gerenciamento dinâmico de processos e processadores.
Embora exista a restrição citada acima, os programas escritos em MPI tendem a serem mais eficientes pelo fato de não haver overhead na carga de processos em tempo de execução.
A diferença básica entre o MPI e o PVM é que, ao contrario do anterior, no MPI existe um único código fonte igual para todas as máquinas e conseqüentemente um único processo rodando.
O MPI funciona da seguinte forma: cada máquina (node) recebe uma copia do código fonte e um nome. Cada node começa a executar o programa a partir da primeira linha de comando utilizando as seguintes diretrizes:
- Executar todas as linhas de comando não nomeadas;
- Executar as linhas de comando nomeadas com o mesmo nome do node;
- Não executar as linhas de comando com o nome de outro node.
Para que o programa siga essas diretrizes, o que é feito é a inclusão de vários comandos if, com a seguinte estrutura:
"
Se eu sou o nodo tal, faço isso... Se não faço aquilo...".
A grande dificuldade que esse sistema acarreta é a necessidade de manter os diversos processos de troca de informações em sincronismo, para que uma máquina não perca muito tempo aguardando que as outras máquinas enviem informações.
Referência: