web-dev-qa-db-fra.com

Implémenter les boucles parallèles pour Python

J'ai un programme Python qui ressemble à ceci:

total_error = []
for i in range(24):
    error = some_function_call(parameters1, parameters2)
    total_error += error

La fonction 'some_function_call' prend beaucoup de temps et je ne trouve pas de moyen facile de réduire la complexité temporelle de la fonction. Existe-t-il un moyen de réduire encore le temps d'exécution lors de l'exécution de tâches parallèles, puis de les additionner dans total_error. J'ai essayé d'utiliser pool et joblib, mais sans succès.

4
thechargedneutron

Vous pouvez également utiliser concurrent.futures dans Python 3, qui est une interface plus simple que multiprocessing. Voir ceci pour plus de détails sur les différences. 

from concurrent import futures

total_error = 0

with futures.ProcessPoolExecutor() as pool:
  for error in pool.map(some_function_call, parameters1, parameters2):
    total_error += error

Dans ce cas, parameters1 et parameters2 doivent être une liste ou une liste indéfinissable de la même taille que le nombre de fois que vous souhaitez exécuter la fonction (24 fois selon votre exemple).

Si paramters<1,2> ne sont pas iterables/mappable, mais que vous souhaitez simplement exécuter la fonction 24 fois, vous pouvez soumettre les travaux pour la fonction pendant le nombre de fois requis et acquérir ultérieurement le résultat à l'aide d'un rappel.

class TotalError:
    def __init__(self):
        self.value = 0

    def __call__(self, r):
        self.value += r.result()

total_error = TotalError()
with futures.ProcessPoolExecutor() as pool:
  for i in range(24):
    future_result = pool.submit(some_function_call, parameters1, parameters2)
    future_result.add_done_callback(total_error)

print(total_error.value)
1
Gerges Dib

Vous pouvez utiliser python multiprocessing:

from multiprocessing import Pool, freeze_support, cpu_count
import os

all_args = [(parameters1, parameters2) for i in range(24)]
#call freeze_support() if in windows
if os.name == "nt":
    freeze_support()
pool = Pool(cpu_count()) #you can use whatever, but your machine core number usually is a good choice (altough maybe not the better)

def wrapped_some_function_call(args): 
    """
    we need to wrap the call to unpack the parameters 
    we build before as a Tuple for being able to use pool.map
    """ 
    sume_function_call(*args) 

results = pool.map(wrapped_some_function_call, all_args)
total_error = sum(results)
2
Netwave