2010-11-04 27 views
4

J'ai besoin de convertir une application threading en une application multiprocessing pour plusieurs raisons (GIL, fuites de mémoire). Heureusement, les threads sont assez isolés et ne communiquent que via Queue.Queue s. Cette primitive est également disponible en multiprocessing donc tout va bien. Maintenant, avant d'entrer dans ce champ de mines, je voudrais obtenir des conseils sur les problèmes à venir:Comment convertir le code de threading Python en code multi-traitement?

  1. Comment faire en sorte que mes objets peuvent être transférés via le Queue? Dois-je fournir quelques __setstate__?
  2. Puis-je compter sur put retournant instantanément (comme avec threadingQueue s)?
  3. Conseils généraux/conseils?
  4. Quelque chose qui vaut la peine de lire en dehors de la Python documentation?
+0

L'initialisation des connexions de base de données dans 'subclass (Process) .__ init__' * est * un problème. : -/ –

+0

Les réponses partielles sont les bienvenues. –

+1

un autre utilisateur a récemment réécrit mon exemple avec la bibliothèque multi-traitement. J'utilisais la file d'attente aussi bien. pourrait valoir le coup d'oeil: http://stackoverflow.com/questions/4072816/ideal-thread-structure-question-involves-multiple-thread-communication – mix

Répondre

5

Réponse à la partie 1:

Tout ce qui doit passer par un multiprocessing.Queue (ou Pipe ou autre) doit être picklable. Cela inclut les types de base tels que tuple s, list s et dict s. Les classes sont également supportées si elles sont de niveau supérieur et pas trop compliquées (vérifiez les détails). Essayer de passer à lambda s échouera cependant.

réponse à la partie 2:

A put se compose de deux parties: Il faut un sémaphore pour modifier la file d'attente et il commence éventuellement un fil d'alimentation. Donc, si aucun autre Process essaie de put au même Queue en même temps (par exemple parce qu'il n'y a qu'un seul Process en train d'écrire), il devrait être rapide. Pour moi, il s'est avéré être assez rapide pour tous les objectifs pratiques.

réponse partielle à la partie 3:

  • La plaine multiprocessing.queue.Queue manque une méthode task_done, donc il ne peut pas être utilisé comme une solution de remplacement directement. (Une sous-classe fournit la méthode.)
  • Le vieil processing.queue.Queue manque d'une méthode qsize et la nouvelle version multiprocessing est inexacte (gardez cela à l'esprit).
  • Étant donné que les sous-fichiers normalement hérités sur fork, il faut prendre soin de les fermer dans les bons processus.