Joblib Parallèle de plusieurs cpu est plus lent que seul
J'ai juste commencé à l'aide de la Joblib module et j'essaie de comprendre comment la fonction Parallèle des œuvres. Ci-dessous est un exemple de cas où la parallélisation conduit à des durées de fonctionnement plus longues, mais je ne comprends pas pourquoi. Mon moteur d'exécution sur 1 processeur était de 51 s vs 217 secondes sur 2 cpu.
Mon hypothèse était que l'exécution de la boucle en parallèle copie des listes a et b de chaque processeur. Puis l'expédition item_n à un seul processeur et item_n+1 pour les autres cpu, exécuter la fonction, puis d'écrire les résultats dans une liste (dans l'ordre). Puis, prenez les 2 éléments et ainsi de suite. Je suis évidemment manque quelque chose.
Est-ce un exemple de mauvais ou de l'utilisation de joblib? Je n'ai tout simplement la structure du code de mal?
Voici l'exemple:
import numpy as np
from matplotlib.path import Path
from joblib import Parallel, delayed
## Create pairs of points for line segments
a = zip(np.random.rand(5000,2),np.random.rand(5000,2))
b = zip(np.random.rand(300,2),np.random.rand(300,2))
## Check if one line segment contains another.
def check_paths(path, paths):
for other_path in paths:
res='no cross'
chck = Path(other_path)
if chck.contains_path(path)==1:
res= 'cross'
break
return res
res = Parallel(n_jobs=2) (delayed(check_paths) (Path(points), a) for points in b)
- Avez-vous votre 1 processus de test avec le même code (seulement
n_jobs=1
) ou avez-vous utilisé une simple boucle for? - Il y a aussi un gros avertissement sur la
joblib
site, afin de protéger le code principal avecif __name__ == '__main__':
. - Juste essayer avec le fil back-end...
- J'ai exactement le même problème. Je suis en cours d'exécution tout de l'intérieur 'si nom == 'principal':', et en fait je suis juste en utilisant l'exemple de leur problème de sortie: = Parallele(n_jobs=2)(en retard(sqrt)(i**2) for i in range(int(1e5))) . Si je le lance avec n_jobs=1, il faut 5 secondes. Si n_jobs=2 à n_jobs=4 (c'est un 4-core de la machine), il faut de 42 secondes!?
- de nombreux calculs ne peuvent bénéficier de calcul parallèle en raison du temps qu'il faut pour carte le calcul pour les autres processeurs, puis retourner les résultats. Je reçois à peu près les mêmes résultats que vous faites avec les joblib exemple. J'ai trouvé les gains les plus importants lorsque l'on compare les éléments d'une liste à une liste d'éléments et d'avoir besoin de retourner la correspondance la plus proche (par exemple, le géocodage ou floue adresse de correspondance).
- Mon parallèle semble être en cours d'exécution plus lent qu'un seul processeur jusqu'à ce que j'ai découvert c'était mon code Timer. Pour voir la fonction en cours d'exécution, ajouter dans la
verbose=50
argument; ceci affichera le temps écoulé et les détails de la tâche. E. g. Parallèle(n_jobs=4, verbose=50)
Vous devez vous connecter pour publier un commentaire.
En bref: je ne peux pas reproduire votre problème. Si vous êtes sur Windows, vous devez utiliser un protecteur pour votre boucle principale: la documentation de
joblib.En parallèle
. Le seul problème que je vois, c'est beaucoup de copie de données dessus, mais vos chiffres semblent irréalistes être causé par l'.En long, voici mes synchronisations avec votre code:
Sur mon i7 3770k (4 coeurs, 8 threads) j'obtiens les résultats suivants pour les différents
n_jobs
:Il y a donc un gain dans l'utilisation de plusieurs processus. Cependant, bien que j'ai quatre coeurs, le gain déjà sature à trois processus. Donc je suppose que le temps d'exécution est limitée par l'accès à la mémoire plutôt que de temps processeur.
Vous devriez noter que les arguments de chaque boucle d'entrée sont copiés dans le processus de l'exécution d'elle. Cela signifie que vous copie
a
pour chaque élément dansb
. C'est inefficace. Ainsi, au lieu de l'accès mondiala
. (Parallel
déviera le processus, la copie de toutes les variables globales pour le nouvellement généré des processus, de sortea
est accessible). Cela me donne le code suivant (avec calendrier et la boucle principale de la garde que la documentation dejoblib
recommande:Calendrier résultats:
La saturation maintenant légèrement déplacé vers
n_jobs=4
qui est la valeur attendue.check_paths
effectue plusieurs calculs redondants qui peuvent facilement être éliminés. Tout d'abord pour tous les éléments deother_paths=a
la lignePath(...)
est exécuté lors de chaque appel. Précalculer que. Deuxièmement, la chaîneres='no cross'
est écrit dans chaque boucle son tour, bien qu'il ne peut changer une fois (suivie d'une pause et de retour). Déplacer la ligne en face de la boucle. Ensuite, le code ressemble à ceci:avec des timings:
Un côté noeud sur votre code, même si je n'ai pas vraiment suivi son but, ce n'était pas liée à votre question,
contains_path
ne retourTrue
if this path completely contains the given path.
(voir la documentation). Par conséquent, votre fonction sera toujours, fondamentalement, un retourno cross
compte tenu de l'aléatoire d'entrée.batch_size
paramètre peut influencer considérablement le fil d'optimisation.En plus de la réponse ci-dessus, et pour référence, il y a deux aspects à cette question, et joblib récentes évolutions aide avec les deux.
Parallèle la création d'un pool de frais généraux: Le problème ici c'est que la création, en parallèle, une piscine est coûteux. Il a été particulièrement coûteux, car le code n'est pas protégé par la "principal" a été exécuté dans chaque catégorie d'emploi à la création de la mise en Parallèle de l'objet. Dans la dernière joblib (encore en bêta), Parallèle peut être utilisé comme un gestionnaire de contexte de limiter le nombre de fois qu'une piscine est créé, et donc l'impact de cette surcharge.
Envoi frais généraux:
il est important de garder à l'esprit que l'envoi d'un élément de la boucle a un rétroprojecteur (beaucoup plus grand que l'itération d'une boucle for sans parallèle). Ainsi, si ces calcul éléments sont très rapides, cette surcharge de dominer le calcul. Dans la dernière joblib, joblib trace le temps d'exécution de chaque tâche, et de commencer le regroupement s'ils sont très rapides. Cela limite fortement l'impact de l'expédition de frais généraux dans la plupart des cas (voir le PR au banc et à la discussion).
Avertissement: je suis l'auteur original de joblib (juste dire à mettre en garde contre les conflits d'intérêts potentiels dans ma réponse, mais là je pense que c'est sans importance).
joblib
-ordonnancement des frais généraux. Serait très responsable pour les inclure dans lajoblib
-documentation. Le joblib-exemples, porté à l'attention des utilisateurs, la plupart de tous les anti-modèles. Auriez-vous l'esprit pour obtenir la documentation du module de l'équipe pour revenir sur ce point d'une façon plus en détail, de façon quantitative de montrer de façon réaliste les coûts de configuration&communication ( avec [nous]-cadencé coûts réels ), de sorte que les utilisateurs peuvent mesure d'un point de rendements négatifs s'apprête à lancer joblib deParallel( )( delayed( .. ) .. )
de l'infrastructure? Vaut le temps de le faire.joblib
des tests de performance + module de la performance de l'auto.la documentation a été envoyé pour votre inspiration & d'autres décisions dans des e-mails. Impatient pour le ci-dessus a annoncé de nouvellesjoblib
version d'arriver en public & à tous le meilleur de vos équipes de recherche.