web-dev-qa-db-fra.com

Utilisation du multitraitement.Process avec un nombre maximal de processus simultanés

J'ai le code Python:

from multiprocessing import Process

def f(name):
    print 'hello', name

if __== '__main__':
    for i in range(0, MAX_PROCESSES):
        p = Process(target=f, args=(i,))
        p.start()

qui fonctionne bien. Cependant, MAX_PROCESSES est variable et peut être n'importe quelle valeur comprise entre 1 et 512. Étant donné que je n'exécute ce code que sur une machine avec des noyaux 8, je dois savoir s'il est possible de limiter le nombre de processus autorisés à s'exécuter simultanément. J'ai examiné multiprocessing.Queue, mais cela ne ressemble pas à ce dont j'ai besoin - ou j'interprète peut-être mal la documentation.

Est-il possible de limiter le nombre de multiprocessing.Processs simultanés en cours d'exécution?

47
Brett

Il serait peut-être plus judicieux d'utiliser multiprocessing.Pool, qui produit un pool de processus de travail basé sur le nombre maximal de cœurs disponibles sur votre système, puis d'alimenter les tâches au fur et à mesure que les cœurs deviennent disponibles.

L'exemple tiré de la documentation standard ( http://docs.python.org/2/library/multiprocessing.html#using-a-pool-of-workers ) montre que vous pouvez également définir manuellement le nombre de cœurs. :

from multiprocessing import Pool

def f(x):
    return x*x

if __== '__main__':
    pool = Pool(processes=4)              # start 4 worker processes
    result = pool.apply_async(f, [10])    # evaluate "f(10)" asynchronously
    print result.get(timeout=1)           # prints "100" unless your computer is *very* slow
    print pool.map(f, range(10))          # prints "[0, 1, 4,..., 81]"

Et il est également utile de savoir qu'il existe la méthode multiprocessing.cpu_count() pour compter le nombre de cœurs sur un système donné, si nécessaire dans votre code.

Edit: Voici un projet de code qui semble fonctionner pour votre cas spécifique:

import multiprocessing

def f(name):
    print 'hello', name

if __== '__main__':
    pool = multiprocessing.Pool() #use all available cores, otherwise specify the number you want as an argument
    for i in xrange(0, 512):
        pool.apply_async(f, args=(i,))
    pool.close()
    pool.join()
68
treddy

plus généralement, cela pourrait aussi ressembler à ceci:

import multiprocessing
def chunks(l, n):
    for i in range(0, len(l), n):
        yield l[i:i + n]

numberOfThreads = 4


if __== '__main__':
    jobs = []
    for i, param in enumerate(params):
        p = multiprocessing.Process(target=f, args=(i,param))
        jobs.append(p)
    for i in chunks(jobs,numberOfThreads):
        for j in i:
            j.start()
        for j in i:
            j.join()

Bien sûr, cette façon de faire est assez cruelle (car elle attend tous les processus dans une jonque avant de continuer avec le bloc suivant). Néanmoins, cela fonctionne bien pour des temps d’approximativement égaux aux appels de fonction.

0
Baedsch