Realizar un bucle for en paralelo en Python 3.2

Posible duplicado:
¿Cómo paralelizo un simple bucle de python?

Soy bastante nuevo en Python (usando Python 3.2) y tengo una pregunta relacionada con la paralelización. Tengo un bucle for que deseo ejecutar en paralelo usando “multiprocesamiento” en Python 3.2:

def computation: global output for x in range(i,j): localResult = ... #perform some computation as a function of i and j output.append(localResult) 

En total, quiero realizar este cálculo para un rango de i = 0 a j = 100. Por lo tanto, quiero crear una serie de procesos que llaman a la función “computación” con un subdominio del rango total. ¿Alguna idea de cómo hacer esto? ¿Hay alguna forma mejor que usar multiprocesamiento?

Más específicamente, quiero realizar una descomposición de dominio y tengo el siguiente código:

 from multiprocessing import Pool class testModule: def __init__(self): self def computation(self, args): start, end = args print('start: ', start, ' end: ', end) testMod = testModule() length = 100 np=4 p = Pool(processes=np) p.map(yes tMod.computation, [(length, startPosition, length//np) for startPosition in range(0, length, length//np)]) 

Recibo un mensaje de error mencionando PicklingError. ¿Alguna idea de cuál podría ser el problema aquí?

    Joblib está diseñado específicamente para envolver todo el multiprocesamiento con el fin de realizar un bucle paralelo simple. Sugiero usar eso en lugar de lidiar con multiprocesamiento directamente.

    El caso simple se ve algo como esto:

     from joblib import Parallel, delayed Parallel(n_jobs=2)(delayed(foo)(i**2) for i in range(10)) # n_jobs = number of processes 

    La syntax es simple una vez que la entiendes. Estamos utilizando la syntax del generador en la que se usa el delayed para llamar a la función foo con sus argumentos contenidos en los paréntesis que siguen.

    En su caso, debe volver a escribir su bucle for con la syntax del generador, o definir otra función (es decir, la función ‘worker’) para realizar las operaciones de una única iteración de bucle y colocarla en la syntax del generador de una llamada a Paralelo.

    En el último caso, harías algo como:

     Parallel(n_jobs=2)(delayed(foo)(parameters) for x in range(i,j)) 

    donde foo es una función que define para manejar el cuerpo de su bucle for. Tenga en cuenta que no desea adjuntar a una lista, ya que Parallel está devolviendo una lista de todos modos.

    En este caso, es probable que desee definir una función simple para realizar el cálculo y obtener localResult .

     def getLocalResult(args): """ Do whatever you want in this func. The point is that it takes x,i,j and returns localResult """ x,i,j = args #unpack args return doSomething(x,i,j) 

    Ahora en su función de cálculo, simplemente crea un grupo de trabajadores y asigna los resultados locales:

     import multiprocessing def computation(np=4): """ np is number of processes to fork """ p = multiprocessing.Pool(np) output = p.map(getLocalResults, [(x,i,j) for x in range(i,j)] ) return output 

    He eliminado el global aquí porque es innecesario (los globales son generalmente innecesarios). En su rutina de llamadas, solo debe hacer output.extend(computation(np=4)) o algo similar.

    EDITAR

    Aquí hay un ejemplo “de trabajo” de su código:

     from multiprocessing import Pool def computation(args): length, startPosition, npoints = args print(args) length = 100 np=4 p = Pool(processes=np) p.map(computation, [(startPosition,startPosition+length//np, length//np) for startPosition in range(0, length, length//np)]) 

    Tenga en cuenta que lo que tenía no funcionó porque estaba usando un método de instancia como su función. el multiprocesamiento inicia nuevos procesos y envía la información entre los procesos a través de pickle , por lo tanto, solo se pueden utilizar los objetos que pueden ser decapados. Tenga en cuenta que realmente no tiene sentido utilizar un método de instancia de todos modos. Cada proceso es una copia del padre, por lo que cualquier cambio al estado que ocurra en los procesos no se propaga de nuevo al padre.