¿Cómo funcionan los subprocesos en Python y cuáles son los errores comunes específicos de los subprocesos de Python?

StackOverflow https://stackoverflow.com/questions/31340

  •  09-06-2019
  •  | 
  •  

Pregunta

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 exhaustiva sobre el tema y no he podido encontrar un buen artículo.

Por lo que puedo decir, ¿solo se puede ejecutar un subproceso a la vez y el subproceso activo cambia cada 10 instrucciones aproximadamente?

¿Dónde hay una buena explicación o puede proporcionar una?También sería muy bueno estar al tanto de los problemas comunes que surgen al utilizar subprocesos con Python.

¿Fue útil?

Solución

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

Del último enlace una cita interesante:

Déjame explicarte qué significa todo eso.Los hilos se ejecutan dentro de la misma máquina virtual y, por lo tanto, se ejecutan en la misma máquina física.Los procesos pueden ejecutarse en la misma máquina física o en otra máquina física.Si arquitecta su aplicación en torno a los subprocesos, no ha hecho nada para acceder a varias máquinas.Por lo tanto, puede escalar a tantos núcleos en la máquina única (que será bastante con el tiempo), pero para alcanzar realmente las escalas web, deberá resolver el problema de la máquina múltiple de todos modos.

Si desea utilizar varios núcleos, procesamiento de py define una API basada en procesos para realizar una paralelización real.El ENERGÍA También incluye algunos puntos de referencia interesantes.

Otros consejos

Python es un lenguaje bastante fácil de usar, pero hay salvedades.Lo más importante que necesita saber es el bloqueo global de intérpretes.Esto permite que sólo 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 puedes poner parte del código en C/C++ si también quieres evitar el GIL.

Por lo tanto, es necesario reconsiderar por qué desea utilizar subprocesos.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 subprocesos.Sin embargo, existen otras alternativas, a saber microhilo.También hay algunos marcos que deberías considerar:

A continuación se muestra un ejemplo básico 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 mediante división de tiempo.Así consiguen 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 al que llamas. start() en el objeto hilo, que invocará automáticamente el run método...

Por supuesto, esto es sólo lo más básico.Con el tiempo querrás aprender sobre semáforos, mutex y bloqueos para la sincronización de subprocesos y el paso de mensajes.

Utilice subprocesos en Python si los trabajadores individuales están realizando operaciones vinculadas de E/S.Si está intentando escalar varios núcleos en una máquina, busque un buen IPC framework para Python o elija un idioma diferente.

Nota: dondequiera que mencione thread me refiero específicamente hilos en python hasta que se indique explícitamente.

Los subprocesos funcionan de manera un poco diferente en Python si vienes de C/C++ fondo.En Python, solo un subproceso puede estar en estado de ejecución en un momento dado. Esto significa que los subprocesos en Python no pueden aprovechar realmente el poder de múltiples núcleos de procesamiento ya que, por diseño, no es posible que los subprocesos se ejecuten en paralelo en múltiples núcleos.

Como la gestión de la 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 global del intérprete).

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 ejecuta un hilo. (incluso si es el hilo principal), se adquiere un GIL y después de algún intervalo de tiempo predefinido, el hilo actual libera el GIL y reaccionado por algún otro hilo (si lo hay).

Why not simply remove GIL?

No es que sea imposible eliminar GIL, es solo que al hacerlo terminamos colocando múltiples bloqueos dentro del intérprete para serializar el acceso, lo que hace que incluso una aplicación con 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 subproceso, lo que nunca es deseado.

So when does thread switching occurs in python?

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

Si un subproceso está realizando operaciones vinculadas a la CPU (procesamiento de imágenes Ex).

En versiones anteriores de Python, el cambio de subproceso solía ocurrir después de un número fijo de instrucciones de Python. De forma predeterminada, estaba configurado en 100Resultó que no es una muy buena política decidir cuándo el cambio debería ocurrir ya que el tiempo dedicado a ejecutar una sola instrucción puede muy salvajemente de milisegundo hasta un segundo. 100 instrucciones independientemente del tiempo que tarden en ejecutarse es una mala política.

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 usando sys.getswitchinterval().Esto se puede modificar usando sys.setswitchinterval()

Si un subproceso está realizando algunas operaciones vinculadas a IO (acceso al sistema de archivos Ex o
E/S de red)

GIL se libera cada vez que el subproceso está esperando que se complete alguna operación de IO.

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..

Una solución sencilla al GIL es la multiprocesamiento módulo.Se puede utilizar como reemplazo directo del módulo de subprocesos, pero utiliza múltiples procesos de intérprete en lugar de subprocesos.Debido a esto, hay un poco más de sobrecarga que el subproceso simple para cosas simples, pero le brinda la ventaja de una paralelización real si la necesita.También se escala fácilmente a múltiples máquinas físicas.

Si necesita una paralelización verdaderamente a gran escala, buscaría más, pero si solo desea escalar a todos los núcleos de una computadora o a algunas diferentes sin todo el trabajo que implicaría implementar un marco más completo, esto es para usted. .

Intente recordar que el GIL está configurado para realizar encuestas de vez en cuando para mostrar la apariencia de múltiples tareas.Esta configuración se puede ajustar, pero ofrezco la sugerencia de que los subprocesos deberían estar trabajando o 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 los mismos núcleos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top