He estado tratando de entender cómo funcionan los subprocesos en Python, y es difícil encontrar buena información sobre cómo funcionan. Puede que me falte un enlace o algo así, pero parece que la documentación oficial no es muy completa sobre el tema y no he podido encontrar una buena reseña.
Por lo que puedo decir, solo se puede ejecutar un hilo a la vez, y el hilo activo cambia cada 10 instrucciones aproximadamente.
¿Dónde hay una buena explicación o puedes dar una? También sería muy bueno estar al tanto de los problemas comunes con los que se encuentra al usar hilos con Python.
Python es un lenguaje bastante fácil de enhebrar, pero hay salvedades. Lo más importante que debe conocer es el bloqueo de intérprete global. Esto permite que solo un hilo acceda al intérprete. Esto significa dos cosas: 1) rara vez se encuentra usando una declaración de bloqueo en Python y 2) si desea aprovechar los sistemas multiprocesador, debe usar procesos separados. EDITAR: También debo señalar que puede poner parte del código en C / C ++ si también desea sortear el GIL.
Por lo tanto, debe volver a considerar por qué desea utilizar hilos. Si desea paralelizar su aplicación para aprovechar la arquitectura de doble núcleo, debe considerar dividir su aplicación en varios procesos.
Si desea mejorar la capacidad de respuesta, debe CONSIDERAR el uso de subprocesos. Sin embargo, existen otras alternativas, a saber, los microhilos . También hay algunos marcos que debería considerar:
fuente
A continuación se muestra una muestra básica de subprocesos. Generará 20 hilos; cada hilo generará su número de hilo. Ejecútelo y observe el orden en que se imprimen.
import threading class Foo (threading.Thread): def __init__(self,x): self.__x = x threading.Thread.__init__(self) def run (self): print str(self.__x) for x in xrange(20): Foo(x).start()
Como ha insinuado, los subprocesos de Python se implementan a través del tiempo. Así es como obtienen el efecto "paralelo".
En mi ejemplo, mi clase Foo extiende el hilo, luego implemento el
run
método, que es donde va el código que le gustaría ejecutar en un hilo. Para iniciar el hilo, llamestart()
al objeto hilo, que invocará automáticamente elrun
método ...Por supuesto, esto es solo lo básico. Eventualmente querrá aprender sobre semáforos, mutex y bloqueos para la sincronización de hilos y el paso de mensajes.
fuente
Use subprocesos en Python si los trabajadores individuales están realizando operaciones vinculadas de E / S. Si está intentando escalar a través de múltiples núcleos en una máquina, busque un buen marco IPC para Python o elija un idioma diferente.
fuente
Nota: donde sea que mencione
thread
me refiero específicamente a hilos en Python hasta que se indique explícitamente.Los subprocesos funcionan de manera un poco diferente en Python si proviene de un
C/C++
segundo plano. En Python, solo un subproceso puede estar en estado de ejecución en un momento dado, lo que significa que los subprocesos en Python no pueden aprovechar realmente el poder de varios núcleos de procesamiento, ya que, por diseño, no es posible que los subprocesos se ejecuten en paralelo en varios núcleos.Como la administración de memoria en Python no es segura para subprocesos, cada subproceso requiere un acceso exclusivo a las estructuras de datos en el intérprete de Python. Este acceso exclusivo se adquiere mediante un mecanismo llamado (bloqueo de interpretación global) .
GIL
Why does python use GIL?
Para evitar que varios subprocesos accedan al estado del intérprete simultáneamente y corrompan el estado del intérprete.
La idea es que cada vez que se está ejecutando un hilo (incluso si es el hilo principal) , se adquiere un GIL y, después de un intervalo de tiempo predefinido, el hilo actual libera el GIL y otro hilo lo vuelve a adquirir (si lo hay).
Why not simply remove GIL?
No es que sea imposible eliminar GIL, es solo que, en el intento de hacerlo, terminamos colocando múltiples bloqueos dentro del intérprete para serializar el acceso, lo que hace que incluso una aplicación de un solo subproceso tenga menos rendimiento.
por lo que el costo de eliminar GIL se compensa con un rendimiento reducido de una aplicación de un solo hilo, lo que nunca se desea.
So when does thread switching occurs in python?
El cambio de hilo ocurre cuando se libera GIL, entonces, ¿cuándo se libera GIL? Hay dos escenarios a tener en cuenta.
Si un subproceso está realizando operaciones vinculadas a la CPU (procesamiento de imágenes Ex).
En las versiones anteriores de Python, el cambio de subproceso solía ocurrir después de un número fijo de instrucciones de Python. Estaba configurado de forma predeterminada en
100
. Resultó que no es una política muy buena para decidir cuándo debe ocurrir el cambio, ya que el tiempo dedicado a ejecutar una sola instrucción puede variar de milisegundos a incluso un segundo. Por lo tanto, liberar GIL después de cada100
instrucción, independientemente del tiempo que tarden en ejecutarse, es una política deficiente.En las nuevas versiones, en lugar de utilizar el recuento de instrucciones como métrica para cambiar de hilo, se utiliza un intervalo de tiempo configurable. El intervalo de cambio predeterminado es de 5 milisegundos. Puede obtener el intervalo de cambio actual utilizando
sys.getswitchinterval()
. Esto se puede modificar usandosys.setswitchinterval()
Si un subproceso está realizando algunas operaciones IO enlazadas (acceso al sistema de archivos Ex o
IO de red)
GIL se libera siempre que el hilo está esperando que se complete la operación de E / S.
Which thread to switch to next?
El intérprete no tiene su propio programador. Qué hilo se programa al final del intervalo es decisión del sistema operativo. .
fuente
Una solución sencilla para el GIL es el módulo de multiprocesamiento . Se puede usar como reemplazo directo del módulo de subprocesos, pero usa múltiples procesos de intérprete en lugar de subprocesos. Debido a esto, hay un poco más de sobrecarga que el simple subproceso para cosas simples, pero le brinda la ventaja de la paralelización real si la necesita. También se escala fácilmente a múltiples máquinas físicas.
Si necesita una paralelización a gran escala, buscaría más, pero si solo desea escalar a todos los núcleos de una computadora o algunas diferentes sin todo el trabajo que implica implementar un marco más completo, entonces esto es para usted. .
fuente
Trate de recordar que el GIL está configurado para sondear de vez en cuando para mostrar la apariencia de múltiples tareas. Esta configuración se puede ajustar con precisión, pero ofrezco la sugerencia de que debería haber trabajo que los subprocesos estén haciendo o que muchos cambios de contexto causarán problemas.
Me atrevería a sugerir varios padres en los procesadores y trataría de mantener trabajos similares en el mismo núcleo (s).
fuente