Je rencontre des problèmes avec le module de multitraitement. J'utilise un pool de travailleurs avec sa méthode de carte pour charger des données à partir de nombreux fichiers et pour chacun d'eux, j'analyse les données avec une fonction personnalisée. Chaque fois qu'un fichier a été traité, j'aimerais qu'un compteur soit mis à jour afin que je puisse garder une trace du nombre de fichiers à traiter. Voici un exemple de code:
def analyze_data( args ):
# do something
counter += 1
print counter
if __== '__main__':
list_of_files = os.listdir(some_directory)
global counter
counter = 0
p = Pool()
p.map(analyze_data, list_of_files)
Je ne trouve pas de solution à cela.
Le problème est que la variable counter
n'est pas partagée entre vos processus: chaque processus séparé crée sa propre instance locale et l'incrémente.
Voir cette section de la documentation pour certaines techniques que vous pouvez utiliser pour partager l'état entre vos processus. Dans votre cas, vous souhaiterez peut-être partager une instance Value
entre vos employés
Voici une version de travail de votre exemple (avec quelques données d'entrée factices). Notez qu'il utilise des valeurs globales que j'essaierais vraiment d'éviter dans la pratique:
from multiprocessing import Pool, Value
from time import sleep
counter = None
def init(args):
''' store the counter for later use '''
global counter
counter = args
def analyze_data(args):
''' increment the global counter, do something with the input '''
global counter
# += operation is not atomic, so we need to get a lock:
with counter.get_lock():
counter.value += 1
print counter.value
return args * 10
if __== '__main__':
#inputs = os.listdir(some_directory)
#
# initialize a cross-process counter and the input lists
#
counter = Value('i', 0)
inputs = [1, 2, 3, 4]
#
# create the pool of workers, ensuring each one receives the counter
# as it starts.
#
p = Pool(initializer = init, initargs = (counter, ))
i = p.map_async(analyze_data, inputs, chunksize = 1)
i.wait()
print i.get()
Classe de compteur sans le bug de condition de course:
class Counter(object):
def __init__(self):
self.val = multiprocessing.Value('i', 0)
def increment(self, n=1):
with self.val.get_lock():
self.val.value += n
@property
def value(self):
return self.val.value
Classe de compteur plus rapide sans utiliser deux fois le verrou intégré de Value
class Counter(object):
def __init__(self, initval=0):
self.val = multiprocessing.RawValue('i', initval)
self.lock = multiprocessing.Lock()
def increment(self):
with self.lock:
self.val.value += 1
@property
def value(self):
return self.val.value
https://eli.thegreenplace.net/2012/01/04/shared-counter-with-pythons-multiprocessinghttps://docs.python.org/2/library/ multiprocessing.html # multiprocessing.sharedctypes.Valuehttps://docs.python.org/2/library/multiprocessing.html#multiprocessing.sharedctypes.RawValue