Estoy un poco confundido acerca de si el multiproceso funciona en Python o no.
Sé que ha habido muchas preguntas sobre esto y he leído muchas de ellas, pero todavía estoy confundido. Sé por mi propia experiencia y he visto a otros publicar sus propias respuestas y ejemplos aquí en StackOverflow que el multiproceso es posible en Python. Entonces, ¿por qué todo el mundo sigue diciendo que Python está bloqueado por GIL y que solo se puede ejecutar un hilo a la vez? Claramente funciona. ¿O hay alguna distinción que no estoy obteniendo aquí?
Muchos carteles / encuestados también siguen mencionando que el enhebrado es limitado porque no utiliza múltiples núcleos. Pero diría que siguen siendo útiles porque funcionan simultáneamente y, por lo tanto, hacen que la carga de trabajo combinada se realice más rápido. Quiero decir, ¿por qué habría un módulo de hilo de Python de otra manera?
Actualizar:
Gracias por todas las respuestas hasta el momento. La forma en que lo entiendo es que el subproceso múltiple solo se ejecutará en paralelo para algunas tareas de E / S, pero solo se puede ejecutar una a la vez para las tareas de múltiples núcleos vinculados a la CPU.
No estoy del todo seguro de lo que esto significa para mí en términos prácticos, así que solo daré un ejemplo del tipo de tarea que me gustaría realizar en múltiples hilos. Por ejemplo, digamos que quiero recorrer una lista muy larga de cadenas y quiero hacer algunas operaciones básicas de cadena en cada elemento de la lista. Si divido la lista, envío cada sublista para que sea procesada por mi código de ciclo / cadena en un nuevo hilo y devuelvo los resultados en una cola, ¿se ejecutarán estas cargas de trabajo aproximadamente al mismo tiempo? Lo más importante, ¿teóricamente acelerará esto el tiempo que lleva ejecutar el script?
Otro ejemplo podría ser si puedo renderizar y guardar cuatro imágenes diferentes usando PIL en cuatro subprocesos diferentes, y ¿esto será más rápido que procesar las imágenes una por una después de la otra? Supongo que este componente de velocidad es lo que realmente me pregunta en lugar de cuál es la terminología correcta.
También conozco el módulo de multiprocesamiento, pero mi principal interés en este momento es para cargas de tareas pequeñas a medianas (10-30 segundos), por lo que creo que el subproceso múltiple será más apropiado porque los subprocesos pueden ser lentos para iniciar.
fuente
Respuestas:
El GIL no evita el enhebrado. Todo lo que hace GIL es asegurarse de que solo un hilo esté ejecutando código Python a la vez; el control todavía cambia entre hilos.
Entonces, lo que GIL evita es hacer uso de más de un núcleo de CPU o CPU independientes para ejecutar subprocesos en paralelo.
Esto solo se aplica al código Python. Las extensiones de C pueden liberar GIL para permitir que varios subprocesos de código C y un subproceso de Python se ejecuten en varios núcleos. Esto se extiende a las E / S controladas por el kernel, como las
select()
llamadas para lecturas y escrituras de sockets, lo que hace que Python maneje los eventos de red de manera razonablemente eficiente en una configuración multiproceso de múltiples núcleos.Lo que hacen muchas implementaciones de servidor es ejecutar más de un proceso de Python, para permitir que el sistema operativo maneje la programación entre procesos para utilizar los núcleos de su CPU al máximo. También puede usar la
multiprocessing
biblioteca para manejar el procesamiento paralelo en múltiples procesos desde una base de código y un proceso principal, si eso se adapta a sus casos de uso.Tenga en cuenta que el GIL solo es aplicable a la implementación de CPython; Jython y IronPython utilizan una implementación de subprocesos diferente (los subprocesos de tiempo de ejecución comunes de Java VM y .NET, respectivamente).
Para abordar su actualización directamente: cualquier tarea que intente obtener un aumento de velocidad de la ejecución paralela, utilizando código Python puro, no verá una aceleración ya que el código Python enhebrado está bloqueado en un hilo que se ejecuta a la vez. Sin embargo, si mezcla extensiones C y E / S (como PIL u operaciones numpy) y cualquier código C puede ejecutarse en paralelo con un hilo Python activo.
El subproceso de Python es excelente para crear una GUI receptiva o para manejar múltiples solicitudes web cortas donde la E / S es el cuello de botella más que el código Python. No es adecuado para paralelizar código Python computacionalmente intensivo, adherirse al
multiprocessing
módulo para tales tareas o delegar en una biblioteca externa dedicada.fuente
urllib.urlopen()
ejemploImage.transform()
,? ), Para llamar a un script de Python desde dentro de una GUI de Python y llamar a múltiplesnumpy.array()
operaciones PIL (por ejemplo ) y numpy (por ejemplo ) con subprocesos. Y proporcionó algunos ejemplos más en su comentario, como el uso de varios hilos para leer archivos (por ejemplof.read()
,?). Sé que no es posible una lista exhaustiva, solo quería los tipos de ejemplos que dio en su actualización. De cualquier manera, acepté su respuesta :)urllib.urlopen()
invocaría sockets de red, esperar la E / S de socket es una excelente oportunidad para cambiar de hilo y hacer otra cosa.Si. :)
Tiene el módulo de roscado de bajo nivel y el módulo de roscado de nivel superior . Pero si simplemente desea utilizar máquinas multinúcleo, el módulo de multiprocesamiento es el camino a seguir.
Cita de los documentos :
fuente
El subproceso está permitido en Python, el único problema es que GIL se asegurará de que solo se ejecute un subproceso a la vez (sin paralelismo).
Entonces, básicamente, si desea realizar múltiples subprocesos en el código para acelerar el cálculo, no lo acelerará ya que solo se ejecuta un subproceso a la vez, pero si lo usa para interactuar con una base de datos, por ejemplo, lo hará.
fuente