Peço desculpas antecipadamente pelo formato de postagem do blog da minha resposta. Não pude evitar fazer uma pequena visão geral do mundo da computação paralela.
É possível categorizar modelos de programação paralela em aproximadamente duas categorias: modelos de fluxo de controle e fluxo de dados.
Os modelos de fluxo de controle tentam fazer o paralelismo funcionar dentro do contexto de um programa de controle explícito, basicamente todos os computadores programáveis atualmente. O problema fundamental que está sendo enfrentado é que essa "arquitetura de Von Neumann" não foi projetada para execução paralela, mas para cálculos seqüenciais eficientes. O paralelismo nesse contexto é obtido pela duplicação de partes dos módulos básicos (memória, controle, aritmética).
A duplicação apenas da aritmética fornece instruções SIMD, todas as ALUs compartilham o mesmo contador de programas (PC) e, portanto, sempre executam a mesma operação em paralelo, embora com dados diferentes.
A duplicação da ALU e do PC, mas mantendo o seqüenciador de instruções dentro da unidade de controle, oferece execução fora de ordem (OoO) que gera algum paralelismo de pipeline. Nesta categoria, você também tem as Técnicas de Palavra Muito Longa (VLWI) e de previsão de ramificação. Você raramente vê essa categoria no nível do software.
Ir um pouco mais longe é duplicar todo o 'núcleo', mas mantendo a memória compartilhada, esses são os processadores multicore atuais que fornecem paralelismo de tarefas (ou threads). Compartilhar memória nesse contexto oferece problemas de concorrência muito, muito difíceis e sutis . Os cálculos paralelos no multicore atual estão, assim, girando completamente em torno de problemas de sincronização / simultaneidade, o cuidadoso equilíbrio de desempenho (sem sincronização) e a semântica desejada (semântica de execução sequencial totalmente sincronizada). Exemplos disso é a PRAM ou mais popular atualmente nos Cilk ofshoots, como fork / join ( IntelTBB , Java.Utils.Concurrency) Os modelos CSP e Actor são modelos de simultaneidade, mas, como mencionado acima, simultaneidade e paralelismo ficam embaçados em um ambiente de memória compartilhada. nb paralelismo é para desempenho, simultaneidade para manter a semântica correta.
A duplicação de memória também oferece computadores em rede que são programados com o MPI e seus tipos, ou apenas arquiteturas não-Von Neumann estranhas, como os processadores de rede em um chip (processador em nuvem, Transputer, Tilera). Modelos de memória como UMA ou NUMA tentam manter a ilusão de memória compartilhada e podem existir no nível de software ou hardware. O MPI mantém o paralelismo no nível do programa e se comunica apenas através da passagem de mensagens. A passagem de mensagens também é usada no nível do hardware para comunicação e simultaneidade (Transputer).
A segunda categoria são modelos de fluxo de dados . Estes foram projetados no início da era do computador como uma maneira de escrever e executar cálculos paralelos, evitando o design de Von Neumann. Estes caíram na moda (para computação paralela) nos anos 80, após o desempenho sequencial ter aumentado exponencialmente. No entanto, muitos sistemas de programação paralela, como o Google MapReduce, o Dryad da Microsoft ou o Concurrent Collections da Intel, são de fato modelos computacionais de fluxo de dados. Em algum momento, eles representam os cálculos como um gráfico e o usam para orientar a execução.
Ao especificar partes dos modelos, você obtém diferentes categorias e semânticas para o modelo de fluxo de dados. A que você restringe a forma do gráfico: DAG (CnC, Dríade), árvore (mapreduce), dígrafo? Há semântica estrita de sincronização ( Luster, programação reativa]? Você proíbe a recursão para poder ter um agendamento estático (StreaMIT) ou fornece uma potência mais expressiva ao ter um agendador dinâmico (Intel CnC)? Existe um limite no número de bordas de entrada ou saída? A semântica de disparo permite disparar o nó quando um subconjunto dos dados recebidos está disponível? São fluxos de arestas de dados (processamento de fluxo) ou tokens de dados únicos (atribuição única estática / dinâmica). Para trabalhos relacionados, você pode começar analisando o trabalho de pesquisa de fluxo de dados de pessoas como Arvind, K. Kavi, j. Sharp, W. Ackerman, R. Jagannathan, etc.
Edit: Por uma questão de integridade. Gostaria de salientar também há paralelos orientado a redução e orientada para o padrão modelos. Para as estratégias de redução, você tem amplamente redução de gráfico e redução de cadeia. Haskell basicamente usa a redução de gráficos, que é uma estratégia muito eficiente em um sistema seqüencial de memória compartilhada. A duplicação de redução de cadeia funciona, mas possui uma propriedade de memória privada que a torna mais adequada para ser implicitamente paralelizada. Os modelos controlados por padrão são as linguagens lógicas paralelas, como o prólogo simultâneo. O modelo Actor também é um modelo orientado a padrões, mas com características de memória privada.
PS. Uso amplamente o termo 'modelo', cobrindo máquinas abstratas para fins formais e de programação.