Ajude a manter o site livre, gratuito e sem propagandas. Colabore!
A computação paralela e distribuída é uma realidade em todas as áreas de pesquisa aplicadas. À primeira vista, pode-se esperar que as aplicações se beneficiam diretamente do ganho em poder computacional. Afinal, se a carga (processo) computacional de uma aplicação for repartida e distribuída em processadores (instâncias de processamentos, threads ou cores), a computação paralela deve ocorrer em um tempo menor do que se a aplicação fosse computada em um único processador (em serial). Entretanto, a tarefa de repartir e distribuir (alocação de tarefas) o processo computacional de uma aplicação é, em muitos casos, bastante desafiadora e pode, em vários casos, levar a códigos computacionais menos eficientes que suas versões seriais.
Repartir e distribuir o processo computacional de uma aplicação sempre é possível, mas nem sempre é possível a computação paralela de cada uma das partes. Por exemplo, vamos considerar a iteração de ponto fixo
(1.1) | |||
(1.2) |
onde é uma função dada e é o ponto inicial da iteração. Para computar devemos processar vezes a iteração (1.1). Se tivéssemos a disposição processadores, poderíamos repartir a carga de processamento em dois, distribuindo o processamento das primeiras iterações para o primeiro processador (o processador ) e as demais para o segundo processador (o processador ). Entretanto, pela característica do processo iterativa, o processador ficaria ocioso, aguardando o processador computar . Se ambas instâncias de processamento compartilharem a mesma memória computacional (memória compartilhada), então, logo que o processador computar ele ficará ocioso, enquanto que o processador computará as últimas iterações. Ou seja, esta abordagem não permite a computação em paralelo, mesmo que reparta e distribua o processo computacional entre duas instâncias de processamento.
Ainda sobre a abordagem acima, caso as instâncias de processamento sejam de memória distribuída (não compartilhem a mesma memória), então o processador e o processador terão de se comunicar, isto é, o processador deverá enviar para a instância de processamento e esta instância deverá receber para, então, iniciar suas computações. A comunicação entre as instâncias de processamento levantam outro desafio que é necessidade ou não da sincronização () eventual entre elas. No caso de nosso exemplo, é a necessidade de sincronização na computação de que está minando a computação paralela.
Em resumo, o design de métodos numéricos paralelos deve levar em consideração a alocação de tarefas, a comunicação e a sincronização entre as instâncias de processamentos. Vamos voltar ao caso da iteração (1.1). Agora, vamos supor que , e a condição inicial é dada. No caso de termos duas instâncias de processamentos disponíveis, podemos computar as iterações em paralelo da seguinte forma. Iniciamos distribuindo às duas instâncias de processamento e . Em paralelo, a instância computa e a instância computa . Para computar a nova iterada , a instância precisa ter acesso a e a instância necessita de . Isto implica na sincronização das instâncias de processamentos, pois uma instância só consegui seguir a computação após a outra instância ter terminado a computação da mesma iteração. Agora, a comunicação entre as instâncias de processamento, depende da arquitetura do máquina. Se as instâncias de processamento compartilham a mesma memória (memória compartilhada), cada uma tem acesso direto ao resultado da outra. No caso de uma arquitetura de memória distribuída, ainda há a necessidade de instruções de comunicação entre as instância, i.e. a instância precisa enviar à instância , a qual precisa receber o valor enviado. A instância precisa enviar à instância , a qual precisa receber o valor enviado. O processo segue análogo para cada iteração até a computação de .
A primeira parte destas notas de aula, restringe-se a implementação de métodos numéricos paralelos em uma arquitetura de memória compartilhada. Os exemplos computacionais são apresentados em linguagem C/C++ com a interface de programação de aplicações (API, Application Programming Interface) OpenMP. A segunda parte, dedica-se a implementação paralela em arquitetura de memória distribuída. Os códigos C/C++ são, então, construídos com a API OpenMPI.
As informações preenchidas são enviadas por e-mail para o desenvolvedor do site e tratadas de forma privada. Consulte a Política de Uso de Dados para mais informações. Aproveito para agradecer a todas/os que de forma assídua ou esporádica contribuem enviando correções, sugestões e críticas!