c++ - hilos - Multithreading versus multiprocesamiento
multithreading c (4)
Soy nuevo en este tipo de programación y necesito tu punto de vista.
Tengo que crear una aplicación, pero no puedo hacer que calcule lo suficientemente rápido. Ya he probado Intel TBB, y es fácil de usar, pero nunca he usado otras bibliotecas.
En la programación multiprocesador, estoy leyendo acerca de OpenMP y Boost para el multihilo, pero no conozco sus pros y contras.
En C ++, ¿cuándo es ventajosa la programación multiproceso en comparación con la programación multiprocesador y viceversa? ¿Cuál es la más adecuada para cálculos pesados o para iniciar muchas tareas ...? ¿Cuáles son sus ventajas y desventajas cuando construimos una aplicación diseñada con ellos? Y finalmente, ¿con qué biblioteca es mejor trabajar?
Hay algunos puntos importantes que creo deberían ser agregados a la excelente respuesta de @Jason.
En primer lugar, el multihilo no siempre es una ilusión, incluso en un solo procesador: hay operaciones que no involucran al procesador. Éstos son principalmente E / S: disco, red, terminal, etc. La forma básica para dicha operación es de bloqueo o síncrona , es decir, su programa espera hasta que se complete la operación y luego continúa. Mientras espera, la CPU cambia a otro proceso / subproceso.
Si tiene algo que puede hacer durante ese tiempo (por ejemplo, computación en segundo plano mientras espera la entrada del usuario, atender otra solicitud, etc.), tiene básicamente dos opciones:
use E / S asíncrona : llama a una E / S no bloqueante proporcionándole una función de devolución de llamada , diciéndole "llame a esta función cuando haya terminado". La llamada vuelve inmediatamente y la operación de E / S continúa en segundo plano. Sigues con las otras cosas.
use multihilo : tiene un hilo dedicado para cada tipo de tarea. Mientras uno espera la llamada de E / S de bloqueo, la otra continúa.
Ambos enfoques son paradigmas de programación difíciles, cada uno tiene sus pros y sus contras.
- con async I / O la lógica de la lógica del programa es menos obvia y es difícil de seguir y depurar. Sin embargo, evita los problemas de seguridad de subprocesos .
- con hilos, el desafío es escribir programas seguros para subprocesos . Las fallas de seguridad del subproceso son errores desagradables que son bastante difíciles de reproducir. El uso excesivo del bloqueo puede conducir a la degradación en lugar de mejorar el rendimiento.
(llegando al multi-procesamiento)
El multiprocesamiento se hizo popular en Windows porque la manipulación de procesos es bastante pesada en Windows (creando un proceso, cambio de contexto, etc.) en oposición a los hilos que son mucho más livianos (al menos este fue el caso cuando trabajé en Win2K).
En Linux / Unix, los procesos son mucho más ligeros. También los subprocesos (AFAIK) en Linux se implementan realmente como un tipo de procesos internos, por lo que no hay ganancia en el cambio de contexto de subprocesos frente a procesos. Sin embargo, debe usar alguna forma de IPC (comunicaciones entre procesos), como memoria compartida, tuberías, cola de mensajes, etc.
En una nota más ligera, mira las preguntas frecuentes de SQLite , que declara "¡Los hilos son malos"! :)
Para responder la primera pregunta: El mejor enfoque es simplemente usar técnicas de subprocesamiento múltiple en su código hasta que llegue al punto en que incluso eso no le proporcione suficiente beneficio. Supongamos que el sistema operativo manejará la delegación a múltiples procesadores si están disponibles.
Si realmente está trabajando en un problema donde el multihilo no es suficiente, incluso con múltiples procesadores (o si está ejecutando un sistema operativo que no está utilizando sus múltiples procesadores), entonces puede preocuparse por descubrir cómo obtener más potencia. . Lo que podría significar procesos de desove a través de una red hacia otras máquinas.
No he usado TBB, pero he usado IPP y he encontrado que es eficiente y está bien diseñado. Boost es portátil.
Solo quería mencionar que el paradigma de Programación basada en flujo ( http://www.jpaulmorrison.com/fbp ) es un enfoque de multiprogramación / multiprocesamiento natural para el desarrollo de aplicaciones. Proporciona una vista de aplicación consistente de alto nivel a bajo nivel. Las implementaciones de Java y C # aprovechan todos los procesadores en su máquina, pero la implementación anterior de C ++ solo usa un procesador. Sin embargo, podría extenderse con bastante facilidad para usar BOOST (o pthreads, supongo) mediante el bloqueo de las conexiones. Empecé a convertirlo para usar fibras, pero no estoy seguro de si tiene sentido continuar en esta ruta. :-) Los comentarios serán apreciados. Por cierto, las implementaciones de Java y C # pueden incluso intercomunicarse usando sockets.
Multithreading significa exactamente eso, ejecuta múltiples hilos. Esto se puede hacer en un sistema de procesador único o en un sistema multiprocesador.
En un sistema de procesador único, cuando se ejecutan varios hilos, la observación real de que la computadora haga varias cosas al mismo tiempo (es decir, multitarea) es una ilusión, porque lo que sucede realmente debajo del capó es que hay un programador de software realizando un corte de tiempo en una sola CPU. De modo que solo una única tarea está sucediendo en un momento determinado, pero el planificador cambia de tareas lo suficientemente rápido como para que nunca note que existen múltiples procesos, hilos, etc., compitiendo por el mismo recurso de CPU.
En un sistema multiprocesador, la necesidad de cortar el tiempo se reduce. El efecto de división de tiempo todavía está allí, porque un sistema operativo moderno podría tener cientos de subprocesos compitiendo por dos o más procesadores, y normalmente nunca hay una relación 1 a 1 en el número de subprocesos con la cantidad de núcleos de procesamiento disponibles. Entonces, en algún punto, un hilo tendrá que detenerse y se iniciará otro hilo en una CPU que los dos hilos están compartiendo. Esto es manejado nuevamente por el programador del sistema operativo. Dicho esto, con un sistema de multiprocesadores, puede tener dos cosas sucediendo al mismo tiempo, a diferencia del sistema de procesador único.
Al final, los dos paradigmas son realmente algo ortogonales en el sentido de que necesitarás multihilo siempre que quieras tener dos o más tareas ejecutándose de forma asincrónica, pero debido a la división del tiempo, no necesariamente necesitas un sistema multiprocesador para lograr ese. Si está tratando de ejecutar múltiples hilos y está haciendo una tarea que es altamente paralela (es decir, tratando de resolver una integral), entonces sí, cuantos más núcleos pueda arrojar a un problema, mejor. No necesariamente necesitará una relación de 1 a 1 entre subprocesos y núcleos de procesamiento, pero al mismo tiempo, no desea escindir tantos subprocesos que termine con toneladas de subprocesos inactivos porque deben esperar a programarse en uno de los núcleos de CPU disponibles. Por otro lado, si sus tareas paralelas requieren algún componente secuencial, es decir, un hilo estará esperando el resultado de otro hilo antes de que pueda continuar, entonces podrá ejecutar más hilos con algún tipo de barrera o método de sincronización para que los hilos que necesitan estar inactivos no están girando usando el tiempo de CPU, y solo los hilos que necesitan ejecutarse compiten por los recursos de la CPU.