Parfor pour Python

Je cherche une réponse définitive au parfor de MATLAB pour Python (Scipy, Numpy).

Existe-t-il une solution similaire à parfor? Sinon, quelle est la complication pour en créer un?

UPDATE: voici un code de calcul numérique typique dont j'ai besoin pour accélérer

import numpy as np

N = 2000
output = np.zeros([N,N])
for i in range(N):
    for j in range(N):
        output[i,j] = HeavyComputationThatIsThreadSafe(i,j)

Un exemple de fonction de calcul lourde est:

import scipy.optimize

def HeavyComputationThatIsThreadSafe(i,j):
    n = i * j

    return scipy.optimize.anneal(lambda x: np.sum((x-np.arange(n)**2)), np.random.random((n,1)))[0][0,0]
39
demandé sur Bzazz 2011-01-13 19:28:55

5 réponses

Il existe de nombreux frameworks Python pour le calcul parallèle . Celui que j'aime le plus est - IPython, mais je ne sais pas trop sur les autres. Dans IPython, un analogue de parfor serait client.MultiEngineClient.map() ou certaines des autres constructions dans la documentation sur le parallélisme rapide et facile .

18
répondu Sven Marnach 2015-05-06 16:31:05

Celui intégré à python serait multiprocessing docs sont ici. J'utilise toujours multiprocessing.Pool avec autant de travailleurs que de processeurs. Ensuite, chaque fois que j'ai besoin de faire une structure de type for-loop, j'utilise Pool.imap

Tant que le corps de votre fonction ne dépend d'aucune itération précédente, vous devriez avoir une accélération presque linéaire. Cela nécessite également que vos entrées et sorties soient pickle - capables, mais c'est assez facile à assurer pour les types standard.

Mise à jour: Certains code pour votre mise à jour fonction juste pour montrer à quel point c'est facile:

from multiprocessing import Pool
from itertools import product

output = np.zeros((N,N))
pool = Pool() #defaults to number of available CPU's
chunksize = 20 #this may take some guessing ... take a look at the docs to decide
for ind, res in enumerate(pool.imap(Fun, product(xrange(N), xrange(N))), chunksize):
    output.flat[ind] = res
26
répondu JudoWill 2011-01-17 17:38:33

J'ai toujours utilisé Python parallèle mais ce n'est pas un analogue complet car je crois qu'il utilise généralement des processus séparés qui peuvent être coûteux sur certains systèmes d'exploitation. Pourtant, si le corps de vos boucles est assez volumineux, cela n'a pas d'importance et peut effectivement avoir des avantages.

4
répondu David Heffernan 2011-01-13 16:36:52

Jupyter Notebook

Pour voir un exemple, considérez que vous voulez écrire l'équivalence de ce code Matlab en Python

matlabpool open 4
parfor n=0:9
   for i=1:10000
       for j=1:10000
           s=j*i   
       end
   end
   n
end
disp('done')

La façon dont on peut écrire ceci en python en particulier dans Jupyter notebook. Vous devez créer une fonction dans le répertoire de travail (je l'ai appelé FunForParFor.py) qui a le

def func(n):
    for i in range(10000):
        for j in range(10000):
            s=j*i
    print(n)

Ensuite, je vais à mon carnet Jupyter et écris le code suivant

import multiprocessing  
import FunForParFor

if __name__ == '__main__':
    pool = multiprocessing.Pool(processes=4)
    pool.map(FunForParFor.func, range(10))
    pool.close()
    pool.join()   
    print('done')

Cela a fonctionné pour moi! Je voulais juste le partager ici, pour vous donner un exemple particulier.

2
répondu rsc05 2017-11-19 08:11:24

J'ai essayé toutes les solutions ici, mais j'ai trouvé que le moyen le plus simple et le plus proche équivalent à matlabs parfor est Prange de numba.

Essentiellement, vous changez une seule lettre dans votre boucle, range à prange:

from numba import autojit, prange

@autojit
def parallel_sum(A):
    sum = 0.0
    for i in prange(A.shape[0]):
        sum += A[i]

    return sum
0
répondu Felix 2018-09-13 08:39:37