¿Mantener el recuento unificado durante el multiprocesamiento?

Tengo un progtwig de Python que ejecuta una simulación de Monte Carlo para encontrar respuestas a preguntas de probabilidad. Estoy usando multiprocesamiento y aquí está en pseudo código

import multiprocessing def runmycode(result_queue): print "Requested..." while 1==1: iterations +=1 if "result found (for example)": result_queue.put("result!") print "Done" processs = [] result_queue = multiprocessing.Queue() for n in range(4): # start 4 processes process = multiprocessing.Process(target=runmycode, args=[result_queue]) process.start() processs.append(process) print "Waiting for result..." result = result_queue.get() # wait for process in processs: # then kill them all off process.terminate() print "Got result:", result 

Me gustaría extender esto para poder mantener un recuento unificado de la cantidad de iteraciones que se han ejecutado. Al igual que si el subproceso 1 se ejecutó 100 veces y el subproceso 2 se ejecutó 100 veces, quiero mostrar un total de 200 iteraciones, como una impresión en la consola. Me refiero a la variable de iterations en el proceso del hilo. ¿Cómo puedo asegurarme de que TODAS las hebras se agreguen a la misma variable? Pensé que usar una versión Global de iterations funcionaría pero no lo hace.

Las variables globales normales no se comparten entre procesos de la forma en que se comparten entre subprocesos. Necesita utilizar una estructura de datos que tenga en cuenta el proceso. Para su caso de uso, un multiprocessing.Value debería funcionar bien:

 import multiprocessing def runmycode(result_queue, iterations): print("Requested...") while 1==1: # This is an infinite loop, so I assume you want something else here with iterations.get_lock(): # Need a lock because incrementing isn't atomic iterations.value += 1 if "result found (for example)": result_queue.put("result!") print("Done") if __name__ == "__main__": processs = [] result_queue = multiprocessing.Queue() iterations = multiprocessing.Value('i', 0) for n in range(4): # start 4 processes process = multiprocessing.Process(target=runmycode, args=(result_queue, iterations)) process.start() processs.append(process) print("Waiting for result...") result = result_queue.get() # wait for process in processs: # then kill them all off process.terminate() print("Got result: {}".format(result)) print("Total iterations {}".format(iterations.value)) 

Algunas notas:

  1. Pasé explícitamente el Value a los niños, para mantener el código compatible con Windows, que no puede compartir las variables globales de lectura / escritura entre padres e hijos.
  2. Protegí el incremento con un locking, porque no es una operación atómica y es susceptible a condiciones de carrera.
  3. if __name__ == "__main__": un if __name__ == "__main__": guard, de nuevo para ayudar con la compatibilidad de Windows, y solo como una mejor práctica general.