multiprocesamiento vs multihilo vs asyncio en Python 3

108

Descubrí que en Python 3.4 hay pocas bibliotecas diferentes para multiprocesamiento / subprocesamiento: multiprocesamiento vs subprocesamiento vs asyncio .

Pero no sé cuál usar o es el "recomendado". ¿Hacen lo mismo o son diferentes? Si es así, ¿cuál se usa para qué? Quiero escribir un programa que use multinúcleos en mi computadora. Pero no sé qué biblioteca debería aprender.

usuario3654650
fuente
1
Quizás soy demasiado estúpido para que AsyncIO ayude
Martin Thoma

Respuestas:

82

Están pensados ​​para propósitos y / o requisitos (ligeramente) diferentes. CPython (una implementación típica de Python en la línea principal) todavía tiene el bloqueo de intérprete global, por lo que una aplicación multiproceso (una forma estándar de implementar el procesamiento paralelo en la actualidad) no es óptima. Es por eso que multiprocessing puede ser preferible threading. Pero no todos los problemas pueden dividirse de manera efectiva en partes [casi independientes], por lo que puede haber una necesidad de comunicaciones intensas entre procesos. Es por eso que multiprocessingpuede que no se prefiera threadingen general.

asyncio(esta técnica está disponible no solo en Python, otros lenguajes y / o frameworks también la tienen, por ejemplo, Boost.ASIO ) es un método para manejar de manera efectiva muchas operaciones de E / S desde muchas fuentes simultáneas sin necesidad de ejecución de código paralelo . Así que es solo una solución (¡muy buena!) Para una tarea en particular, no para el procesamiento paralelo en general.

usuario3159253
fuente
7
Teniendo en cuenta que, si bien es posible que los tres no logren el paralelismo, todos son capaces de realizar tareas simultáneas (sin bloqueo).
sargas
68

[Respuesta rápida]

TL; DR

Tomando la decisión correcta:

Hemos analizado las formas más populares de concurrencia. Pero la pregunta sigue siendo: ¿cuándo elegir cuál? Realmente depende de los casos de uso. Desde mi experiencia (y lectura), tiendo a seguir este pseudo código:

if io_bound:
    if io_very_slow:
        print("Use Asyncio")
    else:
        print("Use Threads")
else:
    print("Multi Processing")
  • CPU Bound => Procesamiento múltiple
  • E / S enlazadas, E / S rápidas, número limitado de conexiones => Multi Threading
  • E / S limitada, E / S lenta, muchas conexiones => Asyncio

Referencia


[ NOTA ]:

  • Si tiene un método de llamada larga (es decir, un método que contiene un tiempo de suspensión o E / S diferida), la mejor opción es el enfoque asyncio , Twisted o Tornado (métodos de co-rutina), que funciona con un solo hilo como concurrencia.
  • asyncio funciona en Python3.4 y posteriores.
  • Tornado y Twisted están listos desde Python2.7
  • uvloop es un asynciobucle de eventos ultrarrápido ( uvloop hace asyncio2-4 veces más rápido).

[ACTUALIZACIÓN (2019)]:

  • Japranto ( GitHub ) es un servidor HTTP de canalización muy rápido basado en uvloop .
Benyamin Jafari
fuente
Entonces, si tengo una lista de URL para solicitar, ¿es mejor usar Asyncio ?
mingchau
1
@mingchau, Sí, pero tenga en cuenta que puede usar desde asynciocuando usa las funciones de espera, la requestbiblioteca no es un método de espera, en lugar de eso, puede usarlo, como la aiohttpbiblioteca o la solicitud asíncrona, etc.
Benyamin Jafari
por favor, extienda en slowIO y fastIO para ir multiproceso o asyncio>?
qrtLs
1
¿Puede indicarnos qué es exactamente io_very_slow
variable
1
El límite de E / S variable significa que su programa pasa la mayor parte del tiempo hablando con un dispositivo lento, como una conexión de red, un disco duro, una impresora o un bucle de eventos con un tiempo de suspensión. Entonces, en el modo de bloqueo, puede elegir entre subprocesos o asyncio, y si su sección delimitadora es muy lenta, la multitarea cooperativa (asyncio) es una mejor opción (es decir, evitar la falta de recursos, los bloqueos y las condiciones de carrera)
Benyamin Jafari
8

Esta es la idea básica:

¿Es IO -BOUND? ---------> USARasyncio

¿ES PESADA LA CPU ? -----> UTILIZARmultiprocessing

ELSE? ----------------------> USARthreading

Así que, básicamente, apégate al subproceso a menos que tengas problemas de IO / CPU.

Farsheed
fuente
0

En el multiprocesamiento , aprovecha varias CPU para distribuir sus cálculos. Dado que cada una de las CPU se ejecuta en paralelo, puede ejecutar varias tareas simultáneamente. Querría utilizar multiprocesamiento para tareas vinculadas a la CPU . Un ejemplo sería intentar calcular la suma de todos los elementos de una lista enorme. Si su máquina tiene 8 núcleos, puede "cortar" la lista en 8 listas más pequeñas y calcular la suma de cada una de esas listas por separado en un núcleo separado y luego simplemente sumar esos números. Obtendrá una aceleración de ~ 8x al hacer eso.

En hilono necesita varias CPU. Imagine un programa que envía muchas solicitudes HTTP a la web. Si usó un programa de un solo subproceso, detendría la ejecución (bloque) en cada solicitud, esperaría una respuesta y luego continuaría una vez que se recibiera una respuesta. El problema aquí es que su CPU no está realmente funcionando mientras espera que algún servidor externo haga el trabajo; ¡podría haber hecho un trabajo útil mientras tanto! La solución es usar hilos: puede crear muchos de ellos, cada uno responsable de solicitar algún contenido de la web. Lo bueno de los subprocesos es que, incluso si se ejecutan en una CPU, la CPU de vez en cuando "congela" la ejecución de un subproceso y salta a la ejecución del otro (se llama cambio de contexto y ocurre constantemente en condiciones no deterministas intervalos). - utilizar enhebrado.

asyncio es esencialmente un subproceso donde no la CPU sino usted, como programador (o en realidad su aplicación), decide dónde y cuándo ocurre el cambio de contexto . En Python, usa una awaitpalabra clave para suspender la ejecución de su corrutina (definida usando una asyncpalabra clave).

Tomasz Bartkowiak
fuente