Comment puis-je paralléLiser une fonction récursive dans Python?
Ma fonction ressemble à ceci: p> Lorsque vous essayez de le paralléléter avec Qu'est-ce qu'un bon moyen (de préférence simple) de le parallementer (pour une seule machine multicœur)? P> ici est le code qui est suspendu: p> multiprocessing.pool. mappe code>, Windows ouvre un nombre infini de processus et suspends. p>
3 Réponses :
OK, désolé pour les problèmes avec cela.
Je vais répondre à une question légèrement différente où Ceci est complexe Parce que deux choses différentes se passent en parallèle: p> Je suis très prudent d'utiliser uniquement la piscine pour calculer la fonction coûteuse. De cette façon, nous ne recevons pas une "explosion" de processus, mais parce que cela est asynchrone, nous devons reporter un lot em> de travail pour le rappel que le travailleur appelle une fois la fonction coûteuse terminée. < / p> Plus que cela, nous devons utiliser un loquet de compte à rebours afin que nous sachions quand tous les appels distincts sur là Peut être un moyen plus simple (je suis à peu près sûr qu'il y a, mais je dois faire d'autres choses), mais cela vous donne peut-être une idée de ce qui est possible: p> ps : J'utilise Python® 3.2 et la laideur ci-dessus est parce que nous retardons le calcul des résultats finaux (sauvegarder l'arborescence) jusqu'à plus tard. Il est possible que quelque chose comme des générateurs ou des contrats à terme pourrait simplifier les choses. P> En outre, je suppose que vous avez besoin d'un cache pour éviter de recalculer inutilement la fonction coûteuse lorsqu'il est appelé avec le même argument que plus tôt. P> Voir aussi La réponse de Yaniv - qui semble être une solution alternative d'inverser la ordre de l'évaluation en étant explicite de profondeur. p> p> f () code> renvoie la somme des valeurs de la liste. C'est-à-dire parce que ce n'est pas clair pour moi de votre exemple quel type de retour de
f () code> serait, et l'utilisation d'un entier rend le code simple à comprendre. P>
f () code> li>
OL>
f () code> sont terminés. P>
1. Définissez la piscine à l'intérieur de la fonction. 2. Avant que la ligne mentionnée, calculez la liste_fralues à l'aide de s'appliquant. 3. Fermez la piscine.
intéressant. Merci pour l'info. Aller jouer avec cela moi-même ...: o)
Andrew pourriez-vous s'il vous plaît expliquer comment la piscine.Appliquez-vous? Parce que cela ne semble pas quelque chose que vous pouvez paraller: appliquer une fonction à un seul argument. Mais quand je l'essaie (même avec une piscine (processus = 1)), je reçois d'excellents résultats.
Je ne suis pas sûr, maintenant. Je peux expliquer ce que Pool.Prappy fait-il juste la fonction ailleurs - mais je ne peux pas expliquer pourquoi cela aide ici (et je pense que ma réponse est fausse). Je me lève avec une œuvre de mienne, mais je reviendrai à cette réponse et je reviendrai ma réponse quand je comprends plus (probablement dans les 12 prochaines heures).
Merci!!. Je vais aussi faire la recherche cela.
Après avoir creusé un peu plus de choses dessus: parce que j'ai fait tous mes tests dans le débogueur de l'IDE, et la piscine fonctionne en dehors du débogueur, c'était plus rapide. Mais dans la comparaison de la vie réelle, ils donnent une heure similaire.
Ok, j'ai mis à jour la réponse et j'appelle cela par jour ... J'espère que ça vous aide. Je suppose qu'il y a une solution beaucoup plus élégante, mais c'est tout ce que je pouvais trouver rapidement.
Andrew, puisque votre solution est complète, elle devrait être la réponse définitive. Mais s'il vous plaît lien vers ma solution partielle mais plus simple ci-dessous.
Après avoir pensé à cela, j'ai trouvé une réponse simple simple, pas complète mais assez bonne:
Je stocke l'identifiant de processus principal initialement et transférez-le aux sous-programmes.
Lorsque j'ai besoin de démarrer un emploi multiprofessionnel, je vérifie le nombre d'enfants du processus principal. S'il est inférieur ou égal à la moitié de mon comptage de la CPU, je l'exécute comme parallèle. Si cela est supérieur à la moitié de mon comptage de la CPU, je l'exécute en série. De cette manière, cela évite les goulots d'étranglement et utilise efficacement les cœurs de la CPU. Vous pouvez régler le nombre de cœurs pour votre cas. Par exemple, vous pouvez le définir sur le nombre exact de cœurs CPU, mais vous ne devez pas le dépasser. P>
def subProgramhWrapper(func, args): func(*args) parent = psutil.Process(main_process_id) children = parent.children(recursive=True) num_cores = int(multiprocessing.cpu_count()/2) if num_cores >= len(children): #parallel run pool = MyPool(num_cores) results = pool.starmap(subProgram, input_params) pool.close() pool.join() else: #serial run for input_param in input_params: subProgramhWrapper(subProgram, input_param)
Quel est le type de retour de
f code>? Il semble que cela renvoie une liste. Mais quel est le type d'élément de liste? C'est ce que je suis bloqué (code similaire à la réponse ci-dessous). Il semble que cela puisse être une liste de listes? Et chacun de ceux-ci peut être une liste? ou est quelque chose qui ne va pas ci-dessus?
X est une feuille d'arbre. Le type de retour est un arbre, dans la notation Lisp [tête, sous-arbres])