2010-10-01 13 views
35

¿Qué es un código simple que hace un procesamiento paralelo en python 2.7? Todos los ejemplos que he encontrado en línea son intrincados e incluyen códigos innecesarios.Procesamiento paralelo en python

¿cómo haré un simple programa de factorización de fuerza bruta donde puedo factorizar 1 entero en cada núcleo (4)? mi programa real probablemente solo necesite 2 núcleos y necesite compartir información.

Sé que en paralelo pitón y otras bibliotecas existen, pero quiero mantener el número de bibliotecas usadas al mínimo, por lo tanto quiero usar la thread y/o multiprocessing bibliotecas, ya que vienen con Python

+0

Aquí es otra manera, he explicado aquí: - [Procesos roscados activos mínimos] [1] [1]: http://stackoverflow.com/a/32337959/4850220 –

Respuesta

29

Una buena manera simple de comenzar con el procesamiento paralelo en python es simplemente el mapeo de grupos en mutiprocesamiento: es como los mapas de python usuales, pero las llamadas a funciones individuales se reparten en los diferentes procesos.

Factoring es un buen ejemplo de esto - se puede por fuerza bruta comprobar todas las divisiones a repartir en todas las tareas disponibles:

from multiprocessing import Pool 
import numpy 

numToFactor = 976 

def isFactor(x): 
    result = None 
    div = (numToFactor/x) 
    if div*x == numToFactor: 
     result = (x,div) 
    return result 

if __name__ == '__main__': 
    pool = Pool(processes=4) 
    possibleFactors = range(1,int(numpy.floor(numpy.sqrt(numToFactor)))+1) 
    print 'Checking ', possibleFactors 
    result = pool.map(isFactor, possibleFactors) 
    cleaned = [x for x in result if not x is None] 
    print 'Factors are', cleaned 

Esto me da

Checking [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31] 
Factors are [(1, 976), (2, 488), (4, 244), (8, 122), (16, 61)] 
+2

Debo añadir que lo anterior funciona, pero probablemente no realice increíbles hazañas de rendimiento paralelo porque la sobrecarga que está invocando (el mapa en paralelo + llamada de función) es todo para calcular un pequeño cantidad de trabajo (un poco de aritmética entera). Lo dejaré como un ejercicio para que el lector piense en cómo amortizar los gastos generales en más divisiones, por ejemplo, cómo cambiar el código anterior para que se llame a "isFactor" una vez para varias divisiones. –

8

mincemeat es la implementación de mapa/reducción más simple que he encontrado. Además, es muy ligero en las dependencias: es un único archivo y hace todo con la biblioteca estándar.

+0

interesante ... lo investigaré – calccrypto

+0

No era lo que estaba buscando realmente – calccrypto

+1

@calccrypto Why not? Saber por qué la carne picada no era perfecta puede ayudar a otros a encontrar una mejor solución. –

1

Estoy de acuerdo que el uso de Pool desde multiprocessing es probablemente la mejor ruta si desea permanecer dentro de la biblioteca estándar. Si está interesado en hacer otros tipos de procesamiento paralelo, pero no aprende nada nuevo (es decir, sigue usando la misma interfaz que multiprocessing), puede probar pathos, que proporciona varias formas de mapas paralelos y tiene prácticamente la misma interfaz que multiprocessing hace.

Python 2.7.6 (default, Nov 12 2013, 13:26:39) 
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import numpy 
>>> numToFactor = 976 
>>> def isFactor(x): 
... result = None 
... div = (numToFactor/x) 
... if div*x == numToFactor: 
...  result = (x,div) 
... return result 
... 
>>> from pathos.multiprocessing import ProcessingPool as MPool 
>>> p = MPool(4) 
>>> possible = range(1,int(numpy.floor(numpy.sqrt(numToFactor)))+1) 
>>> # standard blocking map 
>>> result = [x for x in p.map(isFactor, possible) if x is not None] 
>>> print result 
[(1, 976), (2, 488), (4, 244), (8, 122), (16, 61)] 
>>> 
>>> # asynchronous map (there's also iterative maps too) 
>>> obj = p.amap(isFactor, possible)     
>>> obj 
<processing.pool.MapResult object at 0x108efc450> 
>>> print [x for x in obj.get() if x is not None] 
[(1, 976), (2, 488), (4, 244), (8, 122), (16, 61)] 
>>> 
>>> # there's also parallel-python maps (blocking, iterative, and async) 
>>> from pathos.pp import ParallelPythonPool as PPool 
>>> q = PPool(4) 
>>> result = [x for x in q.map(isFactor, possible) if x is not None] 
>>> print result 
[(1, 976), (2, 488), (4, 244), (8, 122), (16, 61)] 

Además, pathos tiene un paquete de hermana con la misma interfaz, llamada pyina, que se extiende mpi4py, pero proporciona con mapas paralelas que se ejecutan en MPI y se pueden ejecutar utilizando varios programadores.

Otra ventaja es que pathos viene con un serializador mucho mejor del que se puede obtener en python estándar, por lo que es mucho más capaz que multiprocessing de serializar una gama de funciones y otras cosas. Y puedes hacer todo desde el intérprete.

>>> class Foo(object): 
... b = 1 
... def factory(self, a): 
...  def _square(x): 
...  return a*x**2 + self.b 
...  return _square 
... 
>>> f = Foo() 
>>> f.b = 100 
>>> g = f.factory(-1) 
>>> p.map(g, range(10)) 
[100, 99, 96, 91, 84, 75, 64, 51, 36, 19] 
>>> 

Obtener el código aquí: https://github.com/uqfoundation

Cuestiones relacionadas