web-dev-qa-db-fra.com

Traitement parallèle en python

Qu'est-ce qu'un code simple qui traite en parallèle dans Python 2.7? Tous les exemples que j'ai trouvés en ligne sont compliqués et incluent des codes inutiles.

comment ferais-je un programme simple de factorisation d'entiers en force brute où je peux factoriser un entier sur chaque noyau (4)? mon vrai programme n'a probablement besoin que de 2 cœurs et doit partager des informations.

Je sais qu'il existe des bibliothèques parallèles-python et autres, mais je souhaite limiter au minimum le nombre de bibliothèques utilisées. Je souhaite donc utiliser les bibliothèques thread et/ou multiprocessing, car elles viennent avec python.

36
calccrypto

Une méthode simple et efficace pour commencer le traitement parallèle en python consiste simplement à mapper le pool dans un traitement mutuel - c'est comme les mappes python habituelles, mais les appels de fonction individuels sont répartis sur différents nombres de processus.

La factorisation en est un bel exemple: vous pouvez vérifier toutes les divisions réparties sur toutes les tâches disponibles:

from multiprocessing import Pool
import numpy

numToFactor = 976

def isFactor(x):
    result = None
    div = (numToFactor / x)
    if div*x == numToFactor:
        result = (x,div)
    return result

if __== '__main__':
    pool = Pool(processes=4)
    possibleFactors = range(1,int(numpy.floor(numpy.sqrt(numToFactor)))+1)
    print 'Checking ', possibleFactors
    result = pool.map(isFactor, possibleFactors)
    cleaned = [x for x in result if not x is None]
    print 'Factors are', cleaned

Cela me donne

Checking  [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
Factors are [(1, 976), (2, 488), (4, 244), (8, 122), (16, 61)]
30
Jonathan Dursi

mincemeat est la carte la plus simple/réduction de l'implémentation que j'ai trouvée. En outre, il est très léger sur les dépendances - c'est un fichier unique et fait tout avec la bibliothèque standard.

8
Tim McNamara

Je conviens que l'utilisation de Pool à partir de multiprocessing est probablement la meilleure voie à suivre si vous souhaitez rester dans la bibliothèque standard. Si vous souhaitez effectuer d'autres types de traitement parallèle sans apprendre rien de nouveau (en utilisant toujours la même interface que multiprocessing), vous pouvez essayer pathos, qui fournit plusieurs formes de cartes parallèles et a à peu près la même interface que multiprocessing. Est-ce que.

Python 2.7.6 (default, Nov 12 2013, 13:26:39) 
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy
>>> numToFactor = 976
>>> def isFactor(x):
...   result = None
...   div = (numToFactor / x)
...   if div*x == numToFactor:
...     result = (x,div)
...   return result
... 
>>> from pathos.multiprocessing import ProcessingPool as MPool
>>> p = MPool(4)
>>> possible = range(1,int(numpy.floor(numpy.sqrt(numToFactor)))+1)
>>> # standard blocking map
>>> result = [x for x in p.map(isFactor, possible) if x is not None]
>>> print result
[(1, 976), (2, 488), (4, 244), (8, 122), (16, 61)]
>>>
>>> # asynchronous map (there's also iterative maps too)
>>> obj = p.amap(isFactor, possible)                  
>>> obj
<processing.pool.MapResult object at 0x108efc450>
>>> print [x for x in obj.get() if x is not None]
[(1, 976), (2, 488), (4, 244), (8, 122), (16, 61)]
>>>
>>> # there's also parallel-python maps (blocking, iterative, and async) 
>>> from pathos.pp import ParallelPythonPool as PPool
>>> q = PPool(4)
>>> result = [x for x in q.map(isFactor, possible) if x is not None]
>>> print result
[(1, 976), (2, 488), (4, 244), (8, 122), (16, 61)]

De plus, pathos a un paquet frère avec la même interface, appelé pyina, qui exécute mpi4py, mais lui fournit des cartes parallèles qui s'exécutent dans MPI et peuvent être exécutées à l'aide de plusieurs planificateurs.

Un autre avantage est que pathos est fourni avec un sérialiseur bien meilleur que ce que vous pouvez obtenir en python standard. Il est donc beaucoup plus capable que multiprocessing de sérialiser une gamme de fonctions et d’autres choses. Et vous pouvez tout faire de l'interprète.

>>> class Foo(object):
...   b = 1
...   def factory(self, a):
...     def _square(x):
...       return a*x**2 + self.b
...     return _square
... 
>>> f = Foo()
>>> f.b = 100
>>> g = f.factory(-1)
>>> p.map(g, range(10))
[100, 99, 96, 91, 84, 75, 64, 51, 36, 19]
>>> 

Obtenez le code ici: https://github.com/uqfoundation

1
Mike McKerns

Ceci peut être fait élégamment avec Ray , un système qui vous permet de paralléliser et de distribuer facilement votre code Python.

Pour paralléliser votre exemple, vous devez définir votre fonction de carte avec le décorateur @ray.remote, puis l'invoquer avec .remote. Cela garantira que chaque instance de la fonction distante sera exécutée dans un processus différent.

import ray

ray.init()

# Define the function to compute the factors of a number as a remote function.
# This will make sure that a call to this function will run it in a different
# process.
@ray.remote
def compute_factors(x):
    factors = [] 
    for i in range(1, x + 1):
       if x % i == 0:
           factors.append(i)
    return factors    

# List of inputs.
inputs = [67, 24, 18, 312]

# Call a copy of compute_factors() on each element in inputs.
# Each copy will be executed in a separate process.
# Note that a remote function returns a future, i.e., an
# identifier of the result, rather that the result itself.
# This enables the calls to remote function to not be blocking,
# which enables us to call many remote function in parallel. 
result_ids = [compute_factors.remote(x) for x in inputs]

# Now get the results
results = ray.get(result_ids)

# Print the results.
for i in range(len(inputs)):
    print("The factors of", inputs[i], "are", results[i]) 

L'utilisation de Ray sur le module multitraitement présente de nombreux avantages. En particulier, le même code s'exécutera sur une seule machine ainsi que sur un cluster de machines. Pour plus d’avantages de Ray, voir cet article connexe .

0
Ion Stoica