Pregunta ¿Cómo funcionan los hilos en Python, y cuáles son los peligros específicos de Python?


He estado tratando de entender cómo funcionan los hilos en Python, y es difícil encontrar buena información sobre cómo funcionan. Puede que me esté perdiendo un enlace o algo así, pero parece que la documentación oficial no es muy completa sobre el tema, y ​​no he podido encontrar un buen artículo.

Por lo que puedo decir, solo se puede ejecutar un hilo a la vez, y el hilo activo cambia cada 10 instrucciones más o menos?

¿Dónde hay una buena explicación, o puede proporcionar una? También sería muy agradable estar al tanto de los problemas comunes con los que se tropieza al usar hilos con Python.


75
2017-08-27 23:44


origen


Respuestas:


Sí, debido al bloqueo de intérprete global (GIL) solo puede ejecutar un hilo a la vez. Aquí hay algunos enlaces con algunas ideas sobre esto:

Desde el último enlace, una cita interesante:

Déjame explicarte todo lo que eso significa.   Los hilos se ejecutan dentro de la misma virtual   máquina, y por lo tanto se ejecutan en el mismo   máquina física Los procesos pueden ejecutarse   en la misma máquina física o en   otra máquina física. Si tu   diseñar su aplicación alrededor   hilos, no has hecho nada para acceder   máquinas múltiples Entonces, puedes escalar   a tantos núcleos están en el único   máquina (que será bastante   en el tiempo), pero para llegar realmente a la web   escalas, tendrás que resolver el   problema de la máquina múltiple de todos modos.

Si quieres usar multi core, pyprocessing define una API basada en procesos para hacer una paralelización real. los ENERGÍA también incluye algunos puntos de referencia interesantes.


46
2017-08-28 00:19



Python es un lenguaje bastante fácil de usar, pero hay advertencias. Lo más importante que debe saber 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 utilizando 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 algo del código en C / C ++ si también quiere sortear el GIL.

Por lo tanto, debe volver a considerar por qué desea utilizar los hilos. Si desea paralelizar su aplicación para aprovechar la arquitectura de doble núcleo, debe considerar dividir su aplicación en múltiples procesos.

Si desea mejorar la capacidad de respuesta, debe CONSIDERAR el uso de hilos. Sin embargo, hay otras alternativas, a saber microthreading. También hay algunos marcos que debe considerar:


35
2017-08-28 00:00



A continuación se muestra una muestra básica de enhebrado. Engendrará 20 hilos; cada hilo dará salida a 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 hilos de Python se implementan a través del corte de tiempo. Así es como obtienen el efecto "paralelo".

En mi ejemplo, mi clase Foo amplía 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 que llama start() en el objeto de hilo, que invocará automáticamente el run método...

Por supuesto, esto es solo lo básico. Eventualmente querrás aprender sobre semáforos, mutexes y bloqueos para la sincronización de hilos y el envío de mensajes.


19
2017-08-27 23:52



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, encuentre una buena IPC marco para Python o elegir un idioma diferente.


10
2017-08-28 02:34



Una solución fácil para GIL es la multiproceso módulo. Se puede utilizar como un reemplazo en el módulo de subprocesamiento pero utiliza múltiples procesos de Intérprete en lugar de subprocesos. Debido a esto, hay un poco más de sobrecarga que un simple enhebrado para cosas simples, pero le da la ventaja de una paralelización real si la necesita. También escala fácilmente a múltiples máquinas físicas.

Si necesita una paralelización a gran escala mayor que la que yo buscaría más adelante, pero si solo quiere escalar a todos los núcleos de una computadora o unas pocas diferentes sin todo el trabajo que implicaría implementar un marco más completo, entonces esto es para usted .


3
2018-02-06 16:19



Nota:  donde sea que mencione thread me refiero específicamente hilos en python hasta que se establezca explícitamente.

Los hilos funcionan un poco diferente en python si vienes de C/C++ fondo. En python, solo un hilo puede estar en estado de ejecución en un momento determinado. Esto significa que los hilos en python no pueden aprovechar realmente la potencia de múltiples núcleos de procesamiento ya que, por diseño, no es posible que los hilos se ejecuten paralelamente en múltiples núcleos.

Como la gestió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 GIL  (bloqueo de interpretación internacional).

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 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 GIL es liberado por el hilo actual y readquirido por otro hilo (si lo hay).

Why not simply remove GIL?

No es que sea imposible eliminar GIL, es solo que, al hacerlo, terminamos colocando bloqueos mutiples dentro del intérprete para serializar el acceso, lo que hace que incluso una sola aplicación con subprocesos sea menos eficaz.

por lo tanto, el costo de eliminar GIL se compensa con la reducción del rendimiento de una aplicación con un único subproceso, que nunca se desea.

So when does thread switching occurs in python?

El cambio de hilo ocurre cuando se lanza GIL. Entonces, ¿cuándo se libera GIL? Hay dos escenarios para tener en cuenta.

Si un hilo está haciendo operaciones de límite de CPU (procesamiento de imagen Ex).

En las versiones anteriores de python, la conmutación de subprocesos solía ocurrir después de un número fijo de instrucciones de python. Estaba configurado por defecto en 100. Resultó que no es una muy buena política para decidir cuándo debe ocurrir el cambio ya que el tiempo dedicado a ejecutar una sola instrucción puede muy salvajemente de milisegundos a incluso un segundo. Por lo tanto, la liberación de GIL después de cada 100 las instrucciones, independientemente del tiempo que tarden en ejecutarse, son una política deficiente.

En las nuevas versiones, en lugar de utilizar el recuento de instrucciones como una métrica para cambiar el hilo, se utiliza un intervalo de tiempo configurable. El intervalo de cambio predeterminado es de 5 milisegundos. Puede obtener el intervalo de cambio actual usando sys.getswitchinterval(). Esto puede ser alterado usando sys.setswitchinterval()

Si un subproceso está haciendo algunas operaciones IO Bound (acceso al sistema de archivos Ex o
    red IO)

GIL se libera cuando el subproceso está esperando a que se complete alguna operación de E / S.

Which thread to switch to next?

El intérprete no tiene su propio planificador. El hilo que se programa al final del intervalo es la decisión del sistema operativo. .


3
2018-03-30 11:47



Intente recordar que el GIL está configurado para sondear de vez en cuando para mostrar la apariencia de varias tareas. Esta configuración puede ser ajustada, pero ofrezco la sugerencia de que debería haber trabajo que los hilos están haciendo o muchos interruptores de contexto van a causar problemas.

Me atrevería a sugerir múltiples padres en los procesadores y tratar de mantener trabajos similares en el mismo núcleo (s).


2
2017-07-28 22:40