Pido disculpas de antemano por el formato de publicación de blog de mi respuesta. No pude evitar hacer una pequeña descripción del mundo de la computación paralela.
Puede clasificar los modelos de programación paralela en aproximadamente dos categorías: modelos de flujo de control y flujo de datos.
Los modelos de flujo de control intentan hacer que el paralelismo funcione dentro del contexto de un programa de control explícito, básicamente todas las computadoras programables de hoy. El problema fundamental que se está abordando es que dicha 'arquitectura de Von Neumann' no fue diseñada para ejecución paralela, sino computaciones secuenciales eficientes. El paralelismo en dicho contexto se obtiene duplicando partes de los módulos básicos (memoria, control, aritmética).
Duplicar solo la aritmética le da instrucciones SIMD, todas las ALU comparten el mismo contador de programa (PC) y, por lo tanto, siempre ejecutan la misma operación en paralelo, aunque con datos diferentes.
Duplicar ALU y la PC, pero mantener el secuenciador de instrucciones dentro de la unidad de control le brinda ejecución fuera de orden (OoO) que produce cierto paralelismo de canalización. En esta categoría también tiene la Palabra de instrucción muy larga (VLWI) y las técnicas de predicción de ramificaciones. Sin embargo, rara vez ves esta categoría a nivel de software.
Ir un poco más allá es duplicar todo el 'núcleo' pero manteniendo la memoria compartida, estos son los procesadores multinúcleo actuales que le dan paralelismo de tareas (o hilos). Compartir memoria en este contexto le brinda problemas de concurrencia muy, muy difíciles y sutiles . Los cálculos paralelos en el multinúcleo actual, por lo tanto, giran completamente en torno a problemas de sincronización / concurrencia, el cuidadoso equilibrio del rendimiento (sin sincronización) y la semántica deseada (semántica de ejecución secuencial totalmente sincronizada). Ejemplos de esto es el PRAM o más popular en estos días, el Cilk ofshoots como fork / join ( IntelTBB , Java.Utils.Concurrency) Los modelos CSP y Actor son modelos de concurrencia, pero como se mencionó anteriormente, la concurrencia y el paralelismo se vuelven borrosos en un entorno de memoria compartida. Paralelismo nb es para el rendimiento, concurrencia para mantener la semántica correcta.
Duplicar la memoria también le brinda computadoras en red que se programan con MPI y sus características o simplemente arquitecturas extrañas que no son de Von Neumann, como los procesadores de red en un chip (procesador en la nube, Transputer, Tilera). Los modelos de memoria como UMA o NUMA intentan mantener la ilusión de memoria compartida y pueden existir a nivel de software o hardware. MPI mantiene el paralelismo a nivel de programa y solo se comunica a través del paso de mensajes. El paso de mensajes también se utiliza a nivel de hardware para la comunicación y la concurrencia (Transputer).
La segunda categoría son los modelos de flujo de datos . Estos fueron diseñados en los albores de la era de la computadora como una forma de escribir y ejecutar cálculos paralelos, evitando el diseño de Von Neumann. Estos cayeron de moda (para la computación paralela) en los años 80 después de que el rendimiento secuencial aumentara exponencialmente. Sin embargo, muchos sistemas de programación paralela como Google MapReduce, Dryad de Microsoft o Concurrent Collections de Intel son, de hecho, modelos computacionales de flujo de datos. En algún momento representan los cálculos como un gráfico y lo usan para guiar la ejecución.
Al especificar partes de los modelos, obtiene diferentes categorías y semánticas para el modelo de flujo de datos. ¿Cómo restringe la forma del gráfico a: DAG (CnC, Dryad), árbol (mapreduce), dígrafo? ¿Hay una semántica de sincronización estricta ( Lustre, programación reactiva]? ¿No permite la recursividad para poder tener un horario estático (StreaMIT) o proporciona más potencia expresiva al tener un programador dinámico (Intel CnC)? ¿Hay un límite en el número de bordes entrantes o salientes? ¿La semántica de disparo permite disparar el nodo cuando hay disponible un subconjunto de datos entrantes? Son flujos de datos de bordes (procesamiento de flujo) o tokens de datos únicos (asignación única estática / dinámica). Para el trabajo relacionado, puede comenzar mirando el trabajo de investigación de flujo de datos de personas como Arvind, K. Kavi, j. Sharp, W. Ackerman, R. Jagannathan, etc.
Editar: en aras de la integridad. Debo señalar que también hay modelos paralelos basados en la reducción y en el patrón . Para las estrategias de reducción, en general, tiene reducción de gráficos y reducción de cadenas. Haskell básicamente utiliza la reducción de gráficos, que es una estrategia muy eficiente en un sistema secuencial de memoria compartida. La reducción de cadenas duplica el trabajo, pero tiene una propiedad de memoria privada que lo hace más adecuado para ser paralelizado implícitamente. Los modelos basados en patrones son los lenguajes lógicos paralelos, como el prólogo concurrente. El modelo de actor también es un modelo basado en patrones, pero con características de memoria privada.
PD. Uso el término 'modelo' ampliamente, cubriendo máquinas abstractas tanto para fines formales como de programación.