¿Cuál es la diferencia entre programación concurrente y programación paralela?
¿Cuál es la diferencia entre programación concurrente y programación paralela? Pregunté a Google pero no encontré nada que me ayudara a entender esa diferencia. ¿Podrías darme un ejemplo para ambos?
Por ahora encontré esta explicación: http://www.linux-mag.com/id/7411 - pero "la concurrencia es una propiedad del programa" versus "la ejecución paralela es una propiedad de la máquina" no es suficiente para mí - todavía no puedo decir qué es qué.
La programación concurrente considera operaciones que parecen superponerse y se ocupa principalmente de la complejidad que surge debido al flujo de control no determinista. Los costos cuantitativos asociados con los programas simultáneos suelen ser tanto el rendimiento como la latencia. Los programas concurrentes a menudo están vinculados a IO, pero no siempre; por ejemplo, los recolectores de basura concurrentes están completamente en la CPU. El ejemplo pedagógico de un programa concurrente es un rastreador web. Este programa inicia solicitudes de páginas web y acepta las respuestas simultáneamente a medida que los resultados de las descargas están disponibles, acumulando un conjunto de páginas que ya han sido visitadas. El flujo de control no es determinista porque las respuestas no necesariamente se reciben en el mismo orden cada vez que se ejecuta el programa. Esta característica puede dificultar mucho la depuración de programas concurrentes. Algunas aplicaciones son fundamentalmente concurrentes, por ejemplo, los servidores web deben manejar conexiones de clientes al mismo tiempo. Erlang , los flujos de trabajo asíncronos de F# y la biblioteca Akka de Scala son quizás los enfoques más prometedores para la programación altamente concurrente.
La programación multinúcleo es un caso especial de programación paralela. La programación paralela se refiere a operaciones que se superponen con el objetivo específico de mejorar el rendimiento. Las dificultades de la programación concurrente se evitan haciendo que el flujo de control sea determinista. Normalmente, los programas generan conjuntos de tareas secundarias que se ejecutan en paralelo y la tarea principal solo continúa una vez que ha finalizado cada subtarea. Esto hace que los programas paralelos sean mucho más fáciles de depurar que los programas concurrentes. La parte difícil de la programación paralela es la optimización del rendimiento con respecto a cuestiones como la granularidad y la comunicación. Esto último sigue siendo un problema en el contexto de los núcleos múltiples porque existe un costo considerable asociado con la transferencia de datos de una caché a otra. La multiplicación matriz-matriz densa es un ejemplo pedagógico de programación paralela y se puede resolver de manera eficiente utilizando el algoritmo de divide y vencerás de Straasen y atacando los subproblemas en paralelo. Cilk es quizás el enfoque más prometedor para la programación paralela de alto rendimiento en multinúcleos y ha sido adoptado tanto en Threaded Building Blocks de Intel como en la Task Parallel Library de Microsoft (en .NET 4).
Si tu programa está utilizando subprocesos (programación concurrente), no necesariamente se va a ejecutar como tal (ejecución en paralelo), ya que depende de si la máquina puede manejar varios subprocesos.
He aquí un ejemplo visual. Hilos en una máquina sin hilo :
-- -- --
/ \
>---- -- -- -- -- ---->>
Hilos en una máquina roscada :
------
/ \
>-------------->>
Los guiones representan el código ejecutado. Como puede ver, ambos se dividen y ejecutan por separado, pero la máquina roscada puede ejecutar varias piezas separadas a la vez.