threads thread stop processes manejo library example basics python multithreading multiprocessing

stop - thread python 2.7 example



Multiprocesamiento vs Threading Python (8)

Aquí hay algunos pros / contras que se me ocurrieron.

Multiprocesamiento

Pros

  • Espacio de memoria separado
  • El código es generalmente sencillo
  • Aprovecha múltiples CPUs y núcleos
  • Evita las limitaciones de GIL para cPython
  • Elimina la mayoría de las necesidades de primitivas de sincronización a menos que use una memoria compartida (en su lugar, es más bien un modelo de comunicación para IPC)
  • Los procesos hijo son interrumpibles / killables.
  • El módulo de multiprocessing Python incluye abstracciones útiles con una interfaz muy parecida a la de threading.Thread
  • Una necesidad con cPython para el procesamiento enlazado a la CPU

Contras

  • IPC un poco más complicado con más sobrecarga (modelo de comunicación vs. memoria / objetos compartidos)
  • Mayor huella de memoria

Enhebrado

Pros

  • Ligero - espacio de memoria bajo
  • Memoria compartida: facilita el acceso al estado desde otro contexto
  • Le permite crear fácilmente interfaces de usuario sensibles
  • Los módulos de extensión cPython C que lanzan correctamente GIL se ejecutarán en paralelo
  • Gran opción para aplicaciones enlazadas de E / S

Contras

  • cPython - sujeto a la GIL
  • No interrumpible / killable
  • Si no sigue una cola de comandos / modelo de bomba de mensaje (usando el módulo de Queue ), entonces el uso manual de las primitivas de sincronización se convierte en una necesidad (las decisiones son necesarias para la granularidad del bloqueo)
  • El código suele ser más difícil de entender y de hacer bien: el potencial de las condiciones de la carrera aumenta dramáticamente

Estoy tratando de entender las ventajas de multiprocessing sobre threading . Sé que el multiprocesamiento evita el bloqueo global de intérpretes, pero ¿qué otras ventajas existen y los subprocesos no pueden hacer lo mismo?


Como se mencionó en la pregunta, el multiprocesamiento en Python es la única forma real de lograr un verdadero paralelismo. El subprocesamiento múltiple no puede lograr esto porque GIL evita que los subprocesos se ejecuten en paralelo.

Como consecuencia, los subprocesos pueden no ser siempre útiles en Python y, de hecho, incluso pueden dar como resultado un peor rendimiento dependiendo de lo que se está tratando de lograr. Por ejemplo, si está realizando una tarea vinculada a la CPU , como descomprimir archivos gzip o renderizado en 3D (todo lo que hace uso de la CPU), los subprocesos pueden dificultar su rendimiento en lugar de ayudar. En tal caso, desearía utilizar el Multiprocesamiento ya que solo este método se ejecuta en paralelo y ayudará a distribuir el peso de la tarea en cuestión. Podría haber algo de sobrecarga en esto, ya que el multiprocesamiento implica copiar la memoria de un script en cada subproceso, lo que puede causar problemas en aplicaciones de mayor tamaño.

Sin embargo, Multithreading se vuelve útil cuando su tarea está vinculada a IO . Por ejemplo, si la mayor parte de su tarea implica esperar en llamadas a la API , usaría Multithreading porque, por qué no iniciar otra solicitud en otro subproceso mientras espera, en lugar de hacer que la CPU permanezca inactiva.

TL; DR

  • El subprocesamiento múltiple es concurrente y se utiliza para tareas vinculadas a IO
  • El multiprocesamiento logra un verdadero paralelismo y se utiliza para tareas relacionadas con la CPU

El proceso puede tener múltiples hilos. Estos hilos pueden compartir memoria y son las unidades de ejecución dentro de un proceso.

Los procesos se ejecutan en la CPU, por lo que los subprocesos residen en cada proceso. Los procesos son entidades individuales que se ejecutan de forma independiente. Si desea compartir datos o estados entre cada proceso, puede usar una herramienta de almacenamiento de memoria como Cache(redis, memcache) , Files o una Database .


El trabajo de Threading es permitir que las aplicaciones respondan. Supongamos que tiene una conexión de base de datos y necesita responder a las entradas del usuario. Sin subprocesos, si la conexión de la base de datos está ocupada, la aplicación no podrá responder al usuario. Al dividir la conexión de la base de datos en un hilo separado, puede hacer que la aplicación sea más receptiva. Además, como ambos subprocesos están en el mismo proceso, pueden acceder a las mismas estructuras de datos: buen rendimiento y un diseño de software flexible.

Tenga en cuenta que, debido a la GIL, la aplicación no está haciendo dos cosas a la vez, pero lo que hemos hecho es poner el bloqueo de recursos en la base de datos en un subproceso separado para que el tiempo de CPU se pueda cambiar entre esta y la interacción del usuario. El tiempo de CPU se raciona entre los hilos.

El multiprocesamiento es para los momentos en que realmente desea que se haga más de una cosa en un momento dado. Supongamos que su aplicación necesita conectarse a 6 bases de datos y realizar una transformación de matriz compleja en cada conjunto de datos. Poner cada trabajo en un subproceso separado puede ayudar un poco porque cuando una conexión está inactiva, otro puede obtener algo de tiempo de CPU, pero el procesamiento no se realizará en paralelo porque GIL significa que solo está usando los recursos de una CPU . Al poner cada trabajo en un proceso de multiprocesamiento, cada uno puede ejecutarse en su propia CPU y ejecutarse con la máxima eficiencia.


La ventaja clave es el aislamiento. Un proceso que falla no derribará otros procesos, mientras que un subproceso que causa un estruendo probablemente causará estragos en otros subprocesos.


Otra cosa que no se menciona es que depende de qué sistema operativo esté utilizando en lo que respecta a la velocidad. En Windows, los procesos son costosos, por lo que los subprocesos serían mejores en Windows, pero en Unix los procesos son más rápidos que sus variantes de Windows, por lo que usar procesos en Unix es mucho más seguro y rápido de generar.


Otras respuestas se han centrado más en el aspecto multiproceso frente al multiprocesamiento, pero en Python Global Interpreter Lock ( GIL ) debe tenerse en cuenta. Cuando se crea más cantidad (por ejemplo, k ) de subprocesos, generalmente no aumentarán el rendimiento k veces, ya que todavía se ejecutará como una aplicación de un solo subproceso. GIL es un bloqueo global que bloquea todo y permite solo la ejecución de un solo hilo utilizando un solo núcleo. El rendimiento aumenta en lugares donde se utilizan las extensiones C como numpy, Network, I / O, donde se realiza una gran cantidad de trabajo en segundo plano y se libera GIL.
Por lo tanto, cuando se utiliza el subproceso , solo hay un único subproceso a nivel del sistema operativo, mientras que Python crea pseudohilos que se administran completamente mediante el subproceso en sí, pero se ejecutan esencialmente como un solo proceso. La preferencia tiene lugar entre estos pseudo hilos. Si la CPU se ejecuta a su máxima capacidad, es posible que desee cambiar al multiprocesamiento.
Ahora, en el caso de instancias de ejecución autocontenidas, puede optar por un pool. Pero en el caso de datos superpuestos, donde es posible que desee que los procesos se comuniquen, debe utilizar el proceso de multiprocessing.Process .


El módulo de threading utiliza subprocesos, el módulo de multiprocessing utiliza procesos. La diferencia es que los subprocesos se ejecutan en el mismo espacio de memoria, mientras que los procesos tienen memoria separada. Esto hace que sea un poco más difícil compartir objetos entre procesos con multiprocesamiento. Como los hilos usan la misma memoria, se deben tomar precauciones o dos hilos se escribirán en la misma memoria al mismo tiempo. Para esto está el bloqueo de intérprete global.

Los procesos de desove son un poco más lentos que los hilos de desove. Una vez que están corriendo, no hay mucha diferencia.