[Python-es] computación paralela y concurrente

tny a.porrua en gmail.com
Dom Ene 2 01:47:41 CET 2011


El sáb, 01-01-2011 a las 22:56 +0100, David Villa escribió:
> Hola:
> 
> Si no me equivoco, tu callback.Callback es prácticamente equivalente
> al
> functools.partial() de la librería estándar.
> 

Tienes toda la razón, acabo de mirarlo y es exactamente lo mismo.
Así que para la proxima revisión posiblemente marque callback.Callback
como obsoleto y recomiende el uso de functools.partial() en su lugar.
Muchas Gracias.

> Y así a primera vista, diría que gran parte de tu módulo fork puede
> hacerse
> con multiprocessing (de Python-2.6) y concurrent.futures (de
> Python-3.2). De
> éste último estaría muy bien tener un backport. En todo caso tendría
> que
> mirarlo más despacio.
> 
> Saludos 

concurrent.futures no lo conocía, lo acabo de mirar por encima, y parece
muy interesante a la hora de ejecutar funciones de forma paralela, pero
no veo que establezca ningún modo de comunicación entre procesos.


Mi librería pretende ser más sencilla y de mayor nivel que
Multiprocessing.
Personalmente me resulta más intuitivo emplear eventos y callbacks.

De todos modos no son excluyentes, puedes usar mi sistema de eventos, y
también semaforos, queues y demás sistemas de sincronización y
comunicación que multiprocessing ofrece.


un ejemplo que usa pykiss.fork y multiprocessing.Array

#!/usr/bin/env python
#-*- coding:utf-8 -*-

from pykiss import fork
from multiprocessing import Array

arr = Array('i', 3) #este objeto será compartido por todos los procesos

#este proceso hará operaciones con los valores de arr
class Operar_Process(fork.Process):
	def __init__(self, unixsocket):
		fork.Process.__init__(self, unixsocket)
#asignamos los callbacks a los eventos
		self.instance_events['sumar'] = self.sumar
		self.instance_events['multiplicar'] = self.multiplicar
	
#suma lo que haya en arr y lo devuelve con un evento
	def sumar(self, event):
		res = sum(arr)
		self.send_event(keyword='resultado', resultado=res)

#multiplica lo que haya en arr y lo devuelve con un evento
	def multiplicar(self, event):
		res = 1
		for i in arr:
			res*=i
		self.send_event(keyword='resultado', resultado=res)


#este proceso asignará valores a arr
class Asignar_Process(fork.Process):
	def __init__(self, unixsocket):
		fork.Process.__init__(self, unixsocket)
		self.instance_events['asignar'] = self.asignar
	
	def asignar(self, event):
		indice = event['indice']
		valor = event['valor']
		arr[indice]=valor

#Este driver hace más cómodo enviar el evento 'asignar'
class Asignar_Driver(fork.Driver):
	def __setitem__(self, key, value):
		self.send_event(keyword = 'asignar', indice = key,
		 valor = value)

#este callback en el proceso principal mostrará los resultados
def resultado(driver, evento):
	print evento['resultado']

#creamos el objeto principal que gestiona los procesos
control = fork.Control()

#asignamos el callback al evento
control.events['resultado'] = resultado

#creamos los procesos
operar = control.fork(fork.Driver, Operar_Process)
asignar = control.fork(Asignar_Driver, Asignar_Process)

#les mandamos hacer cosas
asignar[0] = 5
asignar[1] = 7
operar.send_event(keyword = 'sumar')

asignar[2] = 12
operar.send_event(keyword = 'sumar')
asignar[0] = 15
operar.send_event(keyword = 'multiplicar')

#Procesamos todos los eventos que hayan llegado al proceso principal
control.do()


Un saludo



Más información sobre la lista de distribución Python-es