Python multiprocesamiento de una función con varias entradas.

En Python, el módulo de multiprocessing se puede usar para ejecutar una función en un rango de valores en paralelo. Por ejemplo, esto produce una lista de las primeras 100000 evaluaciones de f.

 def f(i): return i * i def main(): import multiprocessing pool = multiprocessing.Pool(2) ans = pool.map(f, range(100000)) return ans 

¿Se puede hacer algo similar cuando f toma entradas múltiples pero solo se varía una variable? Por ejemplo, ¿cómo paralelizarías esto?

 def f(i, n): return i * i + 2*n def main(): ans = [] for i in range(100000): ans.append(f(i, 20)) return ans 

Hay varias formas de hacerlo. En el ejemplo dado en la pregunta, simplemente podría definir una función de envoltura

 def g(i): return f(i, 20) 

y pasar esta envoltura al map() . Un enfoque más general es tener una envoltura que tome un solo argumento de tupla y desempaquete la tupla a múltiples argumentos

 def g(tup): return f(*tup) 

o use una expresión lambda equivalente: lambda tup: f(*tup) .

Puedes usar functools.partial

 def f(i, n): return i * i + 2*n def main(): import multiprocessing pool = multiprocessing.Pool(2) ans = pool.map(functools.partial(f, n=20), range(100000)) return ans 

Si usas mi bifurcación de multiprocessing , llamado pathos , puedes obtener pools que toman múltiples argumentos … y también toman funciones lambda . Lo bueno de esto es que no tiene que alterar sus construcciones de progtwigción para que funcionen en paralelo.

 >>> def f(i, n): ... return i * i + 2*n ... >>> from itertools import repeat >>> N = 10000 >>> >>> from pathos.pools import ProcessPool as Pool >>> pool = Pool() >>> >>> ans = pool.map(f, xrange(1000), repeat(20)) >>> ans[:10] [40, 41, 44, 49, 56, 65, 76, 89, 104, 121] >>> >>> # this also works >>> ans = pool.map(lambda x: f(x, 20), xrange(1000)) >>> ans[:10] [40, 41, 44, 49, 56, 65, 76, 89, 104, 121] 

Esta técnica se conoce como Currying: https://en.wikipedia.org/wiki/Currying

Otra forma de hacerlo sin usar functools.partial usando el comando de map clásico dentro de pool.map :

 def f(args): x, fixed = args # FUNCTIONALITY HERE pool = multiprocessing.Pool(multiprocessing.cpu_count() - 1) pool.map(f, map(lambda x: (x, fixed), arguments)) 

Puedes usar el curry del hombre pobre (también conocido como envolverlo):

 new_f = lambda x: f(x, 20) 

entonces llame a new_f(i) .