multithreading - ejemplos - Procesos, hilos, hilos verdes, prototipos, fibras, corotines: ¿cuál es la diferencia?
ejemplos de hilos en python (4)
En general, estoy de acuerdo con la respuesta de Gian, pero tengo diferentes interpretaciones de algunas primitivas de concurrencia. Tenga en cuenta que estos términos a menudo son utilizados de manera inconsistente por diferentes autores. Estas son mis definiciones favoritas (con suerte no muy lejos del consenso moderno).
- Proceso:
- Gestionado por SO
- Cada uno tiene su propio espacio de direcciones virtuales
- Puede ser interrumpido (reemplazado) por el sistema para permitir que se ejecute otro proceso
- Se puede ejecutar en paralelo con otros procesos en diferentes procesadores
- La sobrecarga de memoria de los procesos es alta (incluye tablas de memoria virtual, identificadores de archivos abiertos, etc.)
- El tiempo de sobrecarga para crear y el cambio de contexto entre procesos es relativamente alto
- Trapos:
- Gestionado por SO
- Cada uno está "contenido" dentro de un proceso particular
- Todos los hilos en el mismo proceso comparten el mismo espacio de direcciones virtuales
- Puede ser interrumpido por el sistema para permitir que se ejecute otro subproceso
- Puede ejecutarse en paralelo con otros hilos en diferentes procesadores
- Los gastos generales de memoria y tiempo asociados con los hilos son más pequeños que los procesos, pero aún no son triviales
- (Por ejemplo, típicamente el cambio de contexto implica ingresar al kernel e invocar el programador del sistema).
- Hilos Cooperativos:
- Puede o no ser administrado por SO
- Cada uno está "contenido" dentro de un proceso particular
- En algunas implementaciones, cada una está "contenida" dentro de un hilo de sistema operativo en particular
- No puede ser interrumpido por el sistema para permitir que un compañero cooperativo se ejecute
- (El proceso / hilo que contiene todavía puede ser interrumpido, por supuesto)
- Debe invocar una primitiva de rendimiento especial para permitir que se ejecuten subprocesos cooperativos entre iguales
- Generalmente no se puede ejecutar en paralelo con compañeros cooperativos
- (Aunque algunas personas piensan que es posible: http://ocm.dreamhosters.com/ )
- Hay muchas variaciones en el tema del hilo cooperativo que tienen diferentes nombres:
- Fibras
- Hilos verdes
- Protothreads
- Subprocesos de nivel de usuario (los subprocesos de nivel de usuario pueden ser interrumpibles / preventivos, pero esa es una combinación relativamente inusual)
- Algunas implementaciones de subprocesos cooperativos utilizan técnicas como acumulaciones divididas / segmentadas o incluso asignaciones de montón individualmente a cada marco de llamada para reducir la sobrecarga de memoria asociada con la preasignación de una gran cantidad de memoria para la pila
- Dependiendo de la implementación, llamar a un syscall de bloqueo (como leer desde la red o dormir) provocará que un grupo completo de hilos cooperativos bloquee o implícitamente provoque que el hilo que llama genere
- Corutinas:
- Algunas personas usan "coroutine" e "hilo cooperativo" más o menos sinónimos
- No prefiero este uso
- Algunas implementaciones de coroutine son en realidad hilos de cooperación "poco profundos"; el rendimiento solo puede invocarse mediante el "procedimiento de entrada de corutina"
- La versión superficial (o semi-corutina) es más fácil de implementar que los hilos, ya que cada coroutine no necesita una pila completa (solo un marco para el procedimiento de entrada)
- A menudo, los frameworks de coroutine tienen primitivas de rendimiento que requieren que el invocador indique explícitamente qué control de corrutina debería transferir a
- Algunas personas usan "coroutine" e "hilo cooperativo" más o menos sinónimos
- Generadores:
- Corutinas restringidas (superficiales)
- el rendimiento solo puede devolver el control a cualquier código invocado al generador
- Goroutines:
- Un extraño híbrido de hilos cooperativos y OS
- No puede ser interrumpido (como hilos cooperativos)
- Se puede ejecutar en paralelo en un conjunto de hilos de sistema operativo administrados en tiempo de ejecución de idioma
- Manejadores de eventos:
- Procedimientos / métodos invocados por un despachador de eventos en respuesta a alguna acción que ocurra
- Muy popular para la programación de interfaz de usuario
- Requiere poca o ninguna compatibilidad de idioma / sistema; se puede implementar en una biblioteca
- Como máximo, se puede ejecutar un controlador de eventos a la vez; el despachador debe esperar a que un manejador termine (regrese) antes de comenzar el siguiente
- Hace la sincronización relativamente simple; las diferentes ejecuciones de controladores nunca se superponen en el tiempo
- La implementación de tareas complejas con manejadores de eventos tiende a conducir a "flujo de control invertido" / "extracción de pila"
- Tareas:
- Unidades de trabajo distribuidas por un gerente a un grupo de trabajadores
- Los trabajadores pueden ser hilos, procesos o máquinas
- Por supuesto, el tipo de trabajador que utiliza una biblioteca de tareas tiene un impacto significativo en cómo uno implementa las tareas
- En esta lista de terminología utilizada de manera inconsistente y confusa, "tarea" toma la corona. Particularmente en la comunidad de sistemas integrados, la "tarea" a veces se usa para referirse a "proceso", "hilo" o "controlador de eventos" (generalmente llamado "rutina de servicio de interrupción"). También se usa a veces de forma genérica / informal para referirse a cualquier tipo de unidad de cálculo.
Me molesta una mascota que no puedo dejar de transmitir: no me gusta el uso de la frase "concurrencia verdadera" para "paralelismo de procesador". Es bastante común, pero creo que lleva a mucha confusión.
Para la mayoría de las aplicaciones, creo que los marcos basados en tareas son los mejores para la paralelización. La mayoría de los populares (TBB de Intel, GCD de Apple, TPL y PPL de Microsoft) usan hilos como trabajadores. Desearía que hubiera algunas buenas alternativas que utilizaran procesos, pero no conozco ninguna.
Si está interesado en la concurrencia (a diferencia del paralelismo del procesador), los manejadores de eventos son la forma más segura de hacerlo. Los hilos cooperativos son una alternativa interesante, pero un poco salvaje. No utilice hilos para simultaneidad si le preocupa la fiabilidad y la solidez de su software.
Estoy leyendo sobre concurrencia. Tengo un poco sobre mi cabeza con términos que tienen definiciones confusamente similares. A saber:
- Procesos
- Trapos
- "Hilos verdes"
- Protothreads
- Fibras
- Corutinas
- "Goroutines" en el lenguaje Go
Mi impresión es que las distinciones se basan en (1) si son verdaderamente paralelas o multiplexadas; (2) ya sea que se administre en la CPU, en el sistema operativo o en el programa; y (3..5) algunas otras cosas que no puedo identificar.
¿Existe una guía breve e inequívoca de las diferencias entre estos enfoques del paralelismo?
OK, voy a hacer mi mejor esfuerzo. Hay advertencias en todas partes, pero haré todo lo posible para dar a conocer estos términos y referencias a algo que se aproxime a la definición que he dado.
- Process : administrado por OS (posiblemente) verdaderamente concurrente, al menos en presencia de soporte de hardware adecuado. Existe dentro de su propio espacio de direcciones.
- Thread : administrado por SO, dentro del mismo espacio de direcciones que el padre y todos sus otros hilos. Posiblemente verdaderamente concurrente, y multitarea es preventivo.
- Green Thread : Estas son proyecciones de espacio de usuario del mismo concepto que los hilos, pero no son administradas por el sistema operativo. Probablemente no sea verdaderamente concurrente, excepto en el sentido de que puede haber múltiples hilos de trabajo o procesos que les den tiempo de CPU al mismo tiempo, por lo que probablemente sea mejor considerar esto como entrelazado o multiplexado.
- Protothreads : realmente no podría sacar una definición de estos. Creo que están intercalados y administrados por programa, pero no tomes mi palabra. En mi opinión, se trata esencialmente de una implementación específica de la aplicación del mismo tipo de modelo de "hilos verdes", con la modificación adecuada para el dominio de la aplicación.
- Fibers : administrado por OS. Hilos exactamente, excepto multitarea cooperativa, y por lo tanto no verdaderamente concurrente.
- Coroutines : Exactamente fibras, excepto que no están administradas por el sistema operativo.
- Goroutines : afirman ser diferentes a todo lo demás, pero parecen ser exactamente hilos verdes, como en el caso de los procesos gestionados en un único espacio de direcciones y multiplexados en los hilos del sistema. Quizás alguien con más conocimiento de Go pueda cortar el material de marketing.
También vale la pena señalar que hay otros entendimientos en la teoría de la concurrencia del término "proceso", en el sentido del cálculo del proceso . Esta definición es ortogonal a las anteriores, pero pensé que vale la pena mencionarla para que no surja ninguna confusión en caso de que el proceso se utilice en algún lugar.
Además, tenga en cuenta la diferencia entre parallel y concurrent . Es posible que estuvieras usando el anterior en tu pregunta donde creo que querías decir lo último.
Protothreads son geniales cuando se implementan máquinas de estado secuenciales. Protothreads no son en realidad hilos, sino una abstracción de sintaxis que hace que sea mucho más fácil escribir una máquina de estado de interruptor / caja que tiene que cambiar los estados secuencialmente (de uno a otro, etc.).
He utilizado protothreads para implementar io asincrónico: http://martinschroder.se/asynchronous-io-using-protothreads/
Los Protothreads son solo una implementación de conmutador que actúa como una máquina de estados pero hace que la implementación del software sea mucho más simple. Se basa en la idea de guardar un valor int. Antes de una etiqueta de caso y regresar y luego volver al punto posterior al caso leyendo esa variable y utilizando el interruptor para averiguar dónde continuar. Así que protothread es una implementación secuencial de una máquina de estado.