Pregunta

¿Cuáles son los módulos que se utilizan para escribir aplicaciones multiproceso en Python?Soy consciente de los mecanismos básicos de concurrencia que proporciona el lenguaje y también de Python sin pila, pero ¿cuáles son sus respectivas fortalezas y debilidades?

¿Fue útil?

Solución

Con el fin de aumentar la complejidad:

Utilice el roscado módulo

Pros:

  • Es muy fácil de ejecutar cualquier función (cualquier exigible, de hecho) en su propio hilo.
  • Compartir datos es que si no es fácil (cerraduras nunca son fáciles :), por lo menos sencilla.

Contras:

  • Como se mencionó por hilos Juergen Python en realidad no puede simultáneamente acceder estado en el intérprete ( hay una gran cerradura, el infame intérprete bloqueo global .) lo que esto significa en la práctica es que las discusiones son útil para e / S tareas Bound (redes, la escritura en el disco, y así sucesivamente), pero no del todo útiles para hacer el cálculo concurrente.

Utilice el multiprocesamiento módulo

En el caso de uso simple esto se ve exactamente igual que el uso de threading excepto que cada tarea se ejecuta en su propio proceso no tiene su propio hilo. (Casi literalmente: Si se toma de Eli ejemplo , y reemplazar con threading multiprocessing, Thread, con Process y Queue (módulo) con multiprocessing.Queue, debería funcionar bien.)

Pros:

  • concurrencia real para todas las tareas (sin Global intérprete de bloqueo).
  • escalas para múltiples procesadores, incluso puede escalar a múltiples máquinas .

Contras:

  • Procesos son más lentas que las roscas.
  • El intercambio de datos entre los procesos es más difícil que con hilos.
  • La memoria no se comparte de forma implícita. Usted tiene que compartir de forma explícita o tiene que conservar en vinagre las variables y enviarlos de vuelta y vuelta. Esto es más seguro, pero más difícil. (Si se importa cada vez más los desarrolladores de Python parecen estar empujando a la gente en esta dirección.)

Usar un modelo de eventos, tales como Twisted

Pros:

  • Se obtiene un control muy fino sobre la prioridad, más de lo que se ejecuta cuando.

Contras:

  • Incluso con una buena biblioteca, la programación asincrónica es generalmente más difícil que la programación de rosca, dura tanto en términos de la comprensión de lo que se supone que suceda como en términos de depuración de lo que realmente está sucediendo.

todos casos Asumo que ya entender muchos de los temas involucrados con la multitarea, específicamente el tema complicado de cómo compartir datos entre tareas. Si por alguna razón usted no sabe cuándo y cómo utilizar las cerraduras y las condiciones que tiene que comenzar con aquellos. código multitarea está lleno de sutilezas y trampas, y es realmente la mejor manera de tener una buena comprensión de los conceptos antes de empezar.

Otros consejos

Ya has conseguido una variedad considerable de respuestas, de "hilos falsos" todo el camino a los marcos externos, pero he visto a nadie Queue.Queue mención -. La "salsa secreta" de CPython roscado

Para ampliar: todo el tiempo que no es necesario solapar procesamiento de la CPU-pesada pura-Python (en cuyo caso se necesita multiprocessing - pero viene con su propia implementación Queue, también, para que pueda con algunas precauciones necesarias aplicar el consejo general estoy dando ;-), de Python incorporada threading va a hacer ... pero lo hará mucho mejor si lo usa conocimiento de causa , por ejemplo, de la siguiente manera.

"Forget" memoria compartida, supuestamente, la ventaja principal de rosca vs multiprocesamiento - que no funciona bien, no escala bien, nunca lo ha hecho, nunca lo hará. Utilizar la memoria compartida sólo para las estructuras de datos que se crean una vez antes de desovar sub-hilos y nunca cambió después - para todo lo demás, hacer un solo Thread responsable de ese recurso y comunicarse con ese hilo a través de Queue.

Dedicar un hilo especializado para cada recurso que normalmente piensa para proteger de cerraduras: una estructura de datos mutables o grupo cohesionado de los mismos, una conexión con un proceso externo (una base de datos, un servidor XMLRPC, etc), un archivo externo, etc, etc Obtener un pequeño grupo de subprocesos que va para tareas de propósito general que no tienen o necesitan un recurso dedicado de ese tipo - no hilos de regeneración como y cuando sea necesario, o el thread- conmutación por encima caerá sobre ti.

La comunicación entre dos hilos es siempre a través de Queue.Queue - una forma de paso de mensajes, la única base sana para multiprocesamiento (además transaccional-memoria, que es prometedor, pero para los que no conozco ningún implementaciones de producción digno excepto en Haskell).

Cada hilo dedicado gestión de un solo recurso (o un pequeño conjunto coherente de recursos) escucha las peticiones en un caso específico Queue.Queue. Temas en una lista de espera en un solo Queue.Queue compartida (cola está sólidamente multi-hilo y no que fallar en esto).

Hilos que sólo necesitan hacer cola una solicitud en alguna cola (compartido o dedicado) lo hacen sin esperar los resultados, y seguir adelante. Las discusiones que eventualmente necesitan un resultado o confirmación de petición de cola un par (solicitud, receivingqueue) con una instancia de Queue.Queue que acaba de hacer, y con el tiempo, cuando la respuesta o confirmación es indispensable a fin de proceder, que reciben (en espera ) de su receivingqueue. Asegúrese de que esté listo para obtener respuestas a errores, así como las respuestas o confirmaciones reales (deferreds de Twisted son grandes en la organización de este tipo de respuesta estructurada, por cierto!).

También puede utilizar cola para "parque" instancias de recursos que pueden ser utilizados por un solo hilo, pero nunca se puede compartir entre varios hilos al mismo tiempo (DB conexiones con algunos compoents DBAPI, cursores con los demás, etc.) - este le permite relajar el requisito específico de rosca en favor de una mayor puesta en común (un subproceso del grupo que recibe de la cola compartida una solicitud que necesitan un recurso queueable va a conseguir que el recurso de la cola apppropriate, a la espera de ser necesario, etc, etc).

Twisted es en realidad una buena manera de organizar este minueto (o baile de figuras como puede ser el caso), no sólo gracias a deferreds pero debido a su sonido, la arquitectura base sólida, altamente escalable: se puede organizar cosas para usar hilos o subprocesos sólo cuando realmente se justifica, mientras se hace la mayoría de las cosas normalmente se considera hilo digna en un solo hilo por eventos.

Sin embargo, soy consciente de Twisted no es para todo el mundo - los "dedicar recursos oa la piscina, utilizar la cola de la Wazoo, no haga nunca nada que necesite un bloqueo o, Guido no lo quiera, cualquier procedimiento de sincronización incluso más avanzados, tales como semáforos o condición "enfoque todavía se puede utilizar incluso si sólo no puede envolver su cabeza en torno a las metodologías basadas en eventos asincrónicos, y aún así ofrecer másfiabilidad y rendimiento que cualquier otro método ampliamente aplicable roscado que he topé.

Depende de lo que estás tratando de hacer, pero soy parcial a simplemente usando el módulo threading en la biblioteca estándar, ya que hace que sea muy fácil de tomar cualquier función y sólo ejecutarlo en un hilo separado.

from threading import Thread

def f():
    ...

def g(arg1, arg2, arg3=None):
    ....

Thread(target=f).start()
Thread(target=g, args=[5, 6], kwargs={"arg3": 12}).start()

Y así sucesivamente. Que a menudo tienen una configuración de productor / consumidor utilizando una cola sincronizada proporcionada por el módulo Queue

from Queue import Queue
from threading import Thread

q = Queue()
def consumer():
    while True:
        print sum(q.get())

def producer(data_source):
    for line in data_source:
        q.put( map(int, line.split()) )

Thread(target=producer, args=[SOME_INPUT_FILE_OR_SOMETHING]).start()
for i in range(10):
    Thread(target=consumer).start()

Kamaelia es un marco de Python para crear aplicaciones con muchos procesos de comunicación.

(fuente: kamaelia.org) Kamaelia: la concurrencia se vuelve útil y divertida

En Kamaelia construyes sistemas a partir de Componentes simples que se comunican entre sí..Esto acelera el desarrollo, ayuda enormemente al mantenimiento y también significa que usted construir software naturalmente concurrente.Está destinado a ser accesible por cualquier desarrollador, incluidos los novatos.También lo hace divertido :)

¿Qué tipo de sistemas?Servidores de red, clientes, aplicaciones de escritorio, juegos basados ​​en pygame, sistemas y canales de transcodificación, sistemas de televisión digital, erradicadores de spam, herramientas de enseñanza y mucho más :)

Aquí hay un vídeo de Pycon 2009.Comienza comparando a Kamaelia con Retorcido y Python paralelo y luego hace una demostración práctica de Kamaelia.

Fácil concurrencia con Kamaelia - Parte 1 (59:08)
Fácil concurrencia con Kamaelia - Parte 2 (18:15)

En cuanto a kamaelia, la respuesta anterior no cubre realmente la ventaja aquí. El enfoque de kamaelia proporciona una interfaz unificada, que pragmática no es perfecto, para tratar con hilos, generadores y procesos en un único sistema para la concurrencia.

Fundamentalmente se proporciona una metáfora de una cosa que tiene corriendo las bandejas de entrada y Buzones de salida. Envía mensajes a Buzones de salida, y cuando conectan entre sí, los mensajes fluyen desde Buzones de salida a las bandejas de entrada. Esta metáfora / API sigue siendo el mismo ya sea que esté usando generadores, hilos o procesos, o hablar con otros sistemas.

La parte "no es perfecto" se debe al azúcar sintáctico no se añade hasta el momento de las bandejas de entrada y Buzones de salida (aunque esto está en discusión) -. Hay un enfoque en la seguridad / usabilidad en el sistema

Tomando el ejemplo productor consumidor usando threading desnudo anteriormente, esto se convierte esta en kamaelia:

Pipeline(Producer(), Consumer() )

En este ejemplo que no importa si estos son componentes roscados o de otro modo, la única diferencia es entre ellos desde una perspectiva de uso es la clase base para el componente. componentes del generador se comunican utilizando listas, componentes roscados utilizando Queue.Queues y proceso basado usando os.pipes.

La razón detrás de este enfoque es sin embargo para hacer que sea más difícil hacer difícil de errores de depuración. En enhebrado - o cualquier concurrencia de memoria compartida que tiene, el problema número uno que se enfrenta se rompe accidentalmente actualizaciones de datos compartidos. Mediante el uso de paso de mensajes a eliminar un clase de errores.

Si utiliza el roscado desnudo y cerraduras en todas partes por lo general, está trabajando en el supuesto de que cuando se escribe código que usted no cometer ningún error. Mientras que todos aspiramos a eso, es muy raro que va a pasar. Envolviendo el comportamiento de bloqueo en un solo lugar a simplificar donde las cosas pueden ir mal. (Manipuladores de ayuda de contexto, pero no ayudan con los cambios accidentales fuera del gestor de contextos)

Es evidente que no todas las piezas de código se puede escribir como el paso de mensajes y estilo por lo que kamaelia también tiene un software simple memoria transaccional (STM), que es una idea muy ordenado, con un nombre desagradable en común - que es más como el control de versiones de las variables - es decir, echa un vistazo a algunas variables, actualizarlos y comprometerse espalda. Si usted recibe un choque de enjuagar y repetir.

Enlaces de interés:

De todos modos, espero que sea una respuesta útil. Fwiw, la razón principal detrás de instalación de kamaelia es hacer que la concurrencia más seguro y más fácil de usar en los sistemas de pitón, sin la cola que mueve al perro. (Es decir, el cubo grande de componentes

Puedo entender por qué la otra respuesta kamaelia se modded abajo, ya que incluso a mí se parece más a un anuncio que una respuesta. Como el autor de kamaelia es agradable ver el entusiasmo aunque espero que este contiene un poco más contenido relevante: -)

Y esa es mi forma de decir, por favor tome la advertencia de que esta respuesta es, por definición parcial, pero para mí, el objetivo de kamaelia es tratar de envolver cuál es la mejor práctica de la OMI. Yo sugeriría probar algunos sistemas, y ver cuál funciona para usted. (También si esto no es apropiado para el desbordamiento de pila, lo siento - Soy nuevo en este foro: -)

Me gustaría utilizar los microhilos (Tasklets) de Stackless Python, si tuviera que utilizar hilos en absoluto.

Un juego en línea entera (massivly multijugador) es construir alrededor de Stackless y su principio multihilo -. Ya que el original es sólo para reducir la velocidad para la propiedad massivly multijugador del juego

Temas en el CPython son ampliamente desanimados. Una de las razones es la GIL - una cerradura intérprete mundial - que serializa roscado para muchas partes de la ejecución. Mi experiancia es, que es muy difícil crear aplicaciones rápidas de esta manera. Mi ejemplo codificaciones donde todos más lento con rosca -. Con un núcleo (pero muchas espera una entrada debería haber hecho algo de rendimiento aumenta posible)

Con CPython, en lugar utilizar procesos separados si es posible.

Si usted realmente desea conseguir sus manos sucias, puede intentar utilizando generadores a corrutinas falsos . Es probable que no es el más eficiente en términos de trabajo en cuestión, pero corrutinas le ofrecen un control muy preciso de cooperativa en lugar de multitarea multitarea preventiva encontrará en otro lugar.

Una de las ventajas que encontrará es que, en general, no se necesita cerraduras o mutex al utilizar la multitarea cooperativa, pero la ventaja más importante para mí era la velocidad de conmutación de casi cero entre "hilos". Por supuesto, sin apilado Python se dice que es muy bueno para eso también; y luego está Erlang, si no lo hace Tienes para ser Python.

Probablemente, la mayor desventaja en cooperativo multitarea es la falta general de la solución provisional para el bloqueo de I / O. Y en los corrutinas falsos, también se encontrará con el problema de que no se puede cambiar "hilos" de cualquier cosa, pero el nivel superior de la pila dentro de un hilo.

Después de haber hecho una aplicación incluso un poco complejo con corrutinas falsos, que realmente va a empezar a apreciar el trabajo que va en la planificación de procesos a nivel de sistema operativo.

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