819 votes

Pool.map multitraitement python pour plusieurs arguments

Dans la bibliothèque de multitraitement Python, y at-il une variante de pool.map supportant plusieurs arguments ?

737voto

J.F. Sebastian Points 102961

est-il une variante de la piscine.carte prenant en charge plusieurs arguments?

Python 3.3 inclut pool.starmap() méthode.

Pour les anciennes versions:

import itertools
from multiprocessing import Pool, freeze_support

def func(a, b):
    print a, b

def func_star(a_b):
    """Convert `f([1,2])` to `f(1,2)` call."""
    return func(*a_b)

def main():
    pool = Pool()
    a_args = [1,2,3]
    second_arg = 1
    pool.map(func_star, itertools.izip(a_args, itertools.repeat(second_arg)))

if __name__=="__main__":
    freeze_support()
    main()

Sortie

1 1
2 1
3 1

Remarquez comment itertools.izip() et itertools.repeat() sont utilisés ici.

En raison de la bogue mentionné par @unutbu vous ne pouvez pas utiliser functools.partial() ou des fonctionnalités similaires à la version 2.6 de Python, de sorte que la simple fonction wrapper func_star() doit être définie de manière explicite. Voir aussi la solution proposée par uptimebox.

492voto

senderle Points 41607

Ma première pensée a été d'utiliser des partial, et celle de J. F. Sebastian indiqué, partial fonctionne dans cet exemple en Python >=2.7, donc je suis ce détachement, avec la mise en garde qu'il ne fonctionne pas en 2.6.

Notez également que dans le code ci-dessus, vous êtes de passage le résultat d' harvester(text, case) au lieu de la fonction harvester lui-même. Aussi, vous n'êtes pas de retourner quoi que ce soit; vous aurez à retourner quelque chose pour que ce soit utile.

Je suppose qu' text est la variable qui doit être mappé, tandis que fournit la fonction de mappage des informations supplémentaires sur l'ensemble de la séquence. Il suffit de cartes de chaque élément en case de case[i] + case[0]. C'est un peu différent de ce que vous avez fait, mais je trouve cet exemple plus clair:

from functools import partial

def harvester(text, case):
    X = case[0]
    return text + str(X)

partial_harvester = partial(harvester, case=RAW_DATASET)

if __name__ == '__main__':
    pool = multiprocessing.Pool(processes=6)
    case_data = RAW_DATASET
    pool.map(partial_harvester, case_data, 1)
    pool.close()
    pool.join()

J. F. Sebastian's réponse est plus général, car il vous permet de spécifier unique arguments pour chaque appel. Mais à l'aide de partial est plus simple lorsque l'un des arguments reste le même pour tous les appels.

177voto

imotai Points 56

Je pense que le bas sera mieux

sortie

31voto

zeehio Points 51

Ayant appris itertools dans J. F. Sebastian réponse, j'ai décidé de franchir une nouvelle étape et d'écrire un parmap package qui prend garde à la parallélisation, offrant map et starmap des fonctions en python 2.7 et python 3.2 (et plus tard aussi) qui peut prendre n'importe quel nombre d'arguments de position.

Installation

pip install parmap

Comment paralléliser:

import parmap
# If you want to do:
y = [myfunction(x, argument1, argument2) for x in mylist]
# In parallel:
y = parmap.map(myfunction, mylist, argument1, argument2)

# If you want to do:
z = [myfunction(x, y, argument1, argument2) for (x,y) in mylist]
# In parallel:
z = parmap.starmap(myfunction, mylist, argument1, argument2)

# If you want to do:
listx = [1, 2, 3, 4, 5, 6]
listy = [2, 3, 4, 5, 6, 7]
param = 3.14
param2 = 42
listz = []
for (x, y) in zip(listx, listy):
        listz.append(myfunction(x, y, param1, param2))
# In parallel:
listz = parmap.starmap(myfunction, zip(listx, listy), param1, param2)

J'ai téléchargé parmap de PyPI et à un dépôt github.

Par exemple, la question peut être répondu comme suit:

import parmap

def harvester(case, text):
    X = case[0]
    text+ str(X)

if __name__ == "__main__":
    case = RAW_DATASET  # assuming this is an iterable
    parmap.map(harvester, case, "test", chunksize=1)

19voto

Mike McKerns Points 965

Il y a une fourchette de multiprocessing appelé le pathos (note: utiliser la version sur github) qui n'a pas besoin d' starmap -- des fonctions de la carte miroir de l'API python de la carte, et donc de la carte peut prendre plusieurs arguments. Avec pathos, vous pouvez généralement faire le multitraitement dans l'interprète, au lieu d'être coincé dans l' __main__ bloc. Le Pathos est due pour une sortie, après une légère mise à jour-la plupart du temps la conversion de python 3.x.

  Python 2.7.5 (default, Sep 30 2013, 20:15:49) 
  [GCC 4.2.1 (Apple Inc. build 5566)] on darwin
  Type "help", "copyright", "credits" or "license" for more information.
  >>> def func(a,b):
  ...     print a,b
  ...
  >>>
  >>> from pathos.multiprocessing import ProcessingPool    
  >>> pool = ProcessingPool(nodes=4)
  >>> pool.map(func, [1,2,3], [1,1,1])
  1 1
  2 1
  3 1
  [None, None, None]
  >>>
  >>> # also can pickle stuff like lambdas 
  >>> result = pool.map(lambda x: x**2, range(10))
  >>> result
  [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
  >>>
  >>> # also does asynchronous map
  >>> result = pool.amap(pow, [1,2,3], [4,5,6])
  >>> result.get()
  [1, 32, 729]
  >>>
  >>> # or can return a map iterator
  >>> result = pool.imap(pow, [1,2,3], [4,5,6])
  >>> result
  <processing.pool.IMapIterator object at 0x110c2ffd0>
  >>> list(result)
  [1, 32, 729]

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X