Existe-t-il des outils en Python qui ressemblent au parfor de Matlab? J'ai trouvé ce fil , mais il a quatre ans. Je pensais que quelqu'un ici pourrait avoir une expérience plus récente.
Voici un exemple du type de chose que je voudrais paralléliser:
X = np.random.normal(size=(10, 3))
F = np.zeros((10, ))
for i in range(10):
F[i] = my_function(X[i,:])
où my_function
prend une ndarray
taille (1,3)
et retourne un scalaire.
Au moins, j'aimerais utiliser plusieurs cœurs simultanément - comme parfor. En d'autres termes, supposons un système de mémoire partagée avec 8 à 16 cœurs.
python
parallel-computing
Paul G. Constantine
la source
la source
Réponses:
Joblib fait ce que vous voulez. Le modèle d'utilisation de base est:
où
arg_instances
est la liste des valeurs pour lesquellesmyfun
est calculé en parallèle. La principale restriction est que celamyfun
doit être une fonction de niveau supérieur. Lebackend
paramètre peut être"threading"
ou"multiprocessing"
.Vous pouvez transmettre des paramètres communs supplémentaires à la fonction parallélisée. Le corps de
myfun
peut également faire référence à des variables globales initialisées, les valeurs qui seront disponibles pour les enfants.Les args et les résultats peuvent être à peu près tout avec le backend de threading, mais les résultats doivent être sérialisables avec le backend à multi-traitements.
Dask offre également des fonctionnalités similaires. Cela peut être préférable si vous travaillez avec des données non essentielles ou si vous essayez de paralléliser des calculs plus complexes.
la source
threading
backend souffre du goulot d’étranglement de GIL et lemultiprocessing
backend génère une surcharge importante en raison de la sérialisation de tous les paramètres et valeurs de retour. Voir cette réponse pour les détails de bas niveau du traitement parallèle en Python.map
que vous pouvez utiliser directement. De plus, si vous utilisez mkl compiled numpy, les opérations vectorisées seront automatiquement parallélisées sans que vous ne fassiez rien. Le numpy dans Ananconda est mkl activé par défaut. Il n'y a pas de solution universelle cependant. Joblib est très peu agité et il y avait moins d'otions en 2015.Ce que vous cherchez, c'est Numba , qui peut automatiquement paralléliser une boucle for. De leur documentation
la source
Sans supposer quelque chose de spécial sur le
my_function
choixmultiprocessing.Pool().map()
est une bonne idée pour paralléliser de telles boucles simples.joblib
,dask
, Desmpi
calculs ounumba
comme proposé dans d' autres réponses ne regarde pas apporter aucun avantage pour les cas d'utilisation et ajouter des dépendances inutiles (pour résumer leur surpuissance). L'utilisation de threads comme proposé dans une autre réponse n'est probablement pas une bonne solution, car vous devez être familier avec l'interaction GIL de votre code, sinon votre code devrait principalement effectuer des entrées / sorties.Cela dit
numba
pourrait être une bonne idée pour accélérer le code python pur séquentiel, mais j'estime que cela sort du cadre de la question.Il y a cependant quelques réserves (qui ne devraient pas affecter la plupart des applications):
if __name__ == "__main__"
my_function
ne devrait pas dépendre d'états partagés comme la communication avec des variables globales car les états ne sont pas partagés entre processus. Les fonctions pures (fonctions au sens mathématique) sont des exemples de fonctions qui ne partagent pas d'étatsla source
Mon impression de Parfor est que MATLAB encapsule les détails de l'implémentation, de sorte qu'il pourrait utiliser à la fois le parallélisme de mémoire partagée (comme vous le souhaitez) et le parallélisme de mémoire distribuée (si vous utilisez un serveur d'informatique distribuée MATLAB ).
Si vous voulez un parallélisme de mémoire partagée et que vous exécutez une sorte de boucle de tâche parallèle, le paquet de bibliothèque standard multitraitement est probablement ce que vous voulez, peut-être avec un joli front-end, comme joblib , comme mentionné dans l'article de Doug. La bibliothèque standard ne va pas disparaître, elle est maintenue et présente donc un risque faible.
Il existe également d'autres options, telles que les fonctionnalités parallèles de Parallel Python et IPython . Un coup d’œil rapide à Parallel Python me fait penser que c’est plus proche de l’esprit de parfor, dans la mesure où la bibliothèque encapsule les détails du cas distribué, mais le coût de cette opération est que vous devez adopter leur écosystème. Le coût d'utilisation d'IPython est similaire. vous devez adopter la façon de faire IPython, qui peut ne pas valoir la peine.
Si vous vous souciez de la mémoire distribuée, je vous recommande mpi4py . Lisandro Dalcin fait un excellent travail et mpi4py est utilisé dans les wrappers PETSc Python. Je ne pense donc pas que cela disparaisse de si tôt. Comme le multitraitement, il s’agit d’une interface de niveau (inférieur) avec le parallélisme que parforfor, mais qui est susceptible de durer un certain temps.
la source
Avant de rechercher un outil "boîte noire" pouvant être utilisé pour exécuter en parallèle des fonctions python "génériques", je suggérerais d'analyser comment il
my_function()
est possible de paralléliser à la main.Premièrement, comparez le temps d’exécution de la surcharge de la boucle
my_function(v)
pythonfor
: [C] Lesfor
boucles Python sont assez lentes, le temps d’attentemy_function()
pourrait donc être négligeable.Deuxième vérification s’il existe une simple implémentation vectorielle
my_function(v)
ne nécessitant pas de boucles:F[:] = my_vector_function(X)
(Ces deux premiers points sont assez triviaux, pardonnez-moi si je les ai mentionnés ici pour des raisons de complétude.)
Le troisième point, et le plus important, du moins pour les implémentations CPython, consiste à vérifier si la
my_function
plupart du temps est passé à l' intérieur ou à l' extérieur du verrou d'interpréteur global , ou GIL . Si vous passez du temps en dehors de GIL, vous devez utiliser lethreading
module de bibliothèque standard . ( Voici un exemple). BTW, on pourrait penser à écriremy_function()
comme une extension C juste pour libérer le GIL.Enfin, si
my_function()
ne libère pas le GIL, on pourrait utiliser lemultiprocessing
module .Références: Documents Python sur l'exécution simultanée et intro numpy / scipy sur le traitement parallèle .
la source
Tu peux essayer Julia. C'est assez proche de Python et a beaucoup de constructions MATLAB. La traduction est ici:
Cela rend les nombres aléatoires en parallèle aussi, et concatène simplement les résultats à la fin de la réduction. Cela utilise le multitraitement (vous devez donc
addprocs(N)
ajouter des processus avant de l'utiliser et cela fonctionne également sur plusieurs nœuds d'un HPC, comme indiqué dans cet article de blog ).Vous pouvez également utiliser à la
pmap
place:Si vous voulez un parallélisme entre les threads, vous pouvez utiliser
Threads.@threads
(assurez-vous toutefois de rendre l'algorithme thread-safe). Avant d'ouvrir Julia, définissez la variable d'environnement JULIA_NUM_THREADS, puis procédez comme suit:Ici, je crée un tableau séparé pour chaque thread, afin qu’ils ne se contredisent pas lors de l’ajout au tableau, puis concaténent les tableaux par la suite. Les threads étant assez nouveaux, nous utilisons maintenant directement les threads, mais je suis sûr que des réductions et des maps threadées seront ajoutées comme dans le cas du multitraitement.
la source
Je recommande d'utiliser les fonctions parallèles et différées de la bibliothèque joblib, d'utiliser le module "tempfile" pour créer de la mémoire partagée temporaire pour de grands tableaux, les exemples et l'utilisation peuvent être trouvés ici https://pythonhosted.org/joblib/parallel.html
la source