IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Multiprocessing et classes


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Inscrit en
    Novembre 2011
    Messages
    42
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 42
    Par défaut Multiprocessing et classes
    Bonjour !

    Je vais commencer par présenter ce que j'aimerais savoir :

    J'ai essayer ce bout de script et obtenu ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    >>> from multiprocessing import Process
    >>> class Foo:
    ...     def run(self):
    ...             print(self.stop)
    ...             self.stop = False
    ...             print(self.stop)
    ...     def start(self):
    ...             self.stop = True
    ...             p = Process(target = self.run)
    ...             p.start()
    ...             p.join()
    ... 
    >>> f = Foo()
    >>> f.start()
    True     # Le self.stop "parallèle" est à True
    False    # Le self.stop "parallèle" est bien passé à False
    >>> f.stop
    True     # Le self.stop "parallèle" est à False mais celui de ma classe reste à True ...
    Ma question étant : Comment je pourrait modifier f.stop (et plus globalement f et tous ses attributs) en utilisant les Process ?


    En fait mon problème est dût au thread que j'utilise en ce moment dans mon programme. Il y a beaucoups de threads et, pour une raison qui m'échappe, l'ordonnanceur décide parfois d'accorder 1 ou 2 secondes aux threads en laissant freeze mon programme principal (2 secondes pour faire un "l = []" me parait long ...). J'ai chercher une solution et visiblement le multiprocess serait plus performant. Seulement, ces classes qui tournent en parallèle ont besoin de rester actives et surtout de communiquer avec le programme principal (autrement que par un print ...). Et avant d'implémenter le multiprocess, je me suis rendu compte du problème juste au dessus.

    Donc si quelqu'un à une idée pour "les threads qui font freeze" je suis preneur, mais j'aimerais quand même comprendre le multiprocess

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 741
    Par défaut
    Salut,

    Les "process" de multiprocessing sont des interpréteurs Python différents: chaque process aura sa définition de Foo et les instances sont différentes. Pourquoi ne pas commencer par lire la documentation?
    Vous y trouveriez des exemples de cas d'utilisation simples pour "partager" entre plusieurs process.

    En fait mon problème est dût au thread que j'utilise en ce moment dans mon programme. Il y a beaucoups de threads et, pour une raison qui m'échappe, l'ordonnanceur décide parfois d'accorder 1 ou 2 secondes aux threads en laissant freeze mon programme principal (2 secondes pour faire un "l = []" me parait long ...).
    La question pourrait être est-ce que les threads sont nécessaires? Si oui, est-ce qu'autant de threads sont nécessaires?

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Si tu veux de l'aide sur les threads, il faut dire comment tu les utilises: fais un petit code test (suffisamment complet pour qu'on puisse l'exécuter) avec le problème et montre-le ici.

    Par exemple: avec les bibliothèques graphiques (tkinter, pyqt, ...), des "freeze" sont obtenus lorsque qu'on accède au graphique directement à partir des threads.

    On peut aussi avoir des conflits en accédant à partir des threads à des variables hors threads avec une mauvaise utilisation des verrous.

    J'utilise les threads et je ne rencontre pas tes problèmes. Mais, bien sûr, il faut coder en tenant compte du manuel.

  4. #4
    Membre averti
    Homme Profil pro
    Inscrit en
    Novembre 2011
    Messages
    42
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 42
    Par défaut
    J'ai un générateur de map qui utilise quelque chose comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    >>> from time import sleep
    >>> from threading import Thread
    >>> class MapGenerator(Thread):
    ...     def __init__(self):
    ...             Thread.__init__(self)
    ...             self.stop = False
    ...             self.etages = []
    ...             self.etage_en_cours_de_generation = []
    ...             self.id_etage_en_cours = 1
    ...             self.start()                            # Je n'ai pas mon code sous les yeux donc je sais plus
    ...     def get_etage(self, id):                        # comment j'apelle start (self ou Thread) mais ça marche
    ...             if id == self.id_etage_en_cours:
    ...                     self.id_etage_en_cours += 1     # Derniere étage généré, donc on en prévois un nouveau
    ...             return self.etages[id]
    ...     def run(self):
    ...             while not self.stop:
    ...                     if self.id_etage_en_cours == len(self.etages):
    ...                             generer_etage(self.id_etage_en_cours)
    ...                             self.etages.append(self.etage_en_cours_de_generation)
    ...                     sleep(10)
    ...     def generer_etage(self, id_etage):
    ...             # Genère l'étage dans self.etage_en_cours_de_generation
    ...             pass
    Grosso modo, j'ai une liste dont l'index correspond à chaque étage. Chaque étage est généré dans une liste (etage_en_cours_de_generation) à laquelle je n'accède jamais de l'extérieur. le temps de génération peut être extrèmement long et je ne peux donc pas attendre d'avoir atteint un étage avant de le générer (j'ai déjà atteint les 10 minutes pour un étage). Mais même si je met du temps avant de générer une salle, il me faut du temps pour l'atteindre, et donc cette méthode fonctionne sans problème. J'ai une sécurité qui attend que l'étage soit créer avant de le demander mais il ne m'as jamais servi pour autre chose qu'un test.
    Pour l'utilisation de cette classe, je n'ai qu'une méthode publique (en dehors des Thread et Object) qui et get_etage(self, etage)

    J'y avais pas pensé sur le coups, mais les autres threads servent au path finding et sont effacé quand il n'y a plus d'ennemis (Vérifié à coups de print, il s'arrêtent bel et bien) donc ces threads n'ont peut être pas de problème (en tout cas je n'ai pas plus de freeze avec)


    En écrivant ce post je viens de me rendre compte que cette méthode me permettrait de facilement utiliser le multiprocess si je ne partage que la fameuse liste d'étages via Array ou Value, je vais essayer ça.

  5. #5
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 741
    Par défaut
    Salut,

    Que mange "generer_etage(self, id_etage)" ?

    Dit autrement, quel est la raison technique qui explique:
    le temps de génération peut être extrêmement long et je ne peux donc pas attendre d'avoir atteint un étage avant de le générer (j'ai déjà atteint les 10 minutes pour un étage)
    L'autre question est par quoi est appelé:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    ...     def get_etage(self, id):                        # comment j'apelle start (self ou Thread) mais ça marche
    ...             if id == self.id_etage_en_cours:
    ...                     self.id_etage_en_cours += 1     # Derniere étage généré, donc on en prévois un nouveau
    ...             return self.etages[id]
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  6. #6
    Membre averti
    Homme Profil pro
    Inscrit en
    Novembre 2011
    Messages
    42
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 42
    Par défaut
    La raison technique c'est le nombre de calcul à faire pour générer l'étage. En gros un étage comprend un nombre de salle variable et leur génération fait énormément appel à random, ce qui la rend plutôt longue ... A niveau de "perception humaine", le temps de chargement ne se sent pas avant 10 salles (et encore, on sent juste que c'est pas instantané, mais on attend pas non plus) mais ayant un peut testé le résultat, j'ai remarqué qu'on se retrouvais vite aux étage à plus de 50 salles et là les temps de chargements commencent vraiment à être long (en sachant que le but est de n'avoir aucune limite sur le nombre de salle, même si c'est impossible).

    J'ai une classe qui gère la gestion de la map (son affichage, les case accessibles ou non, les entités, etc.) et quand on change d'étage, je fait un bête "self.grid = self.generateur_de_map.get_etage(self.etage)". La variable "generateur_de_map" est initialisée dans le constructeur et n'est utiliser que pour la fonction "get_etage", c'est le seul et unique accès que je lui donne (en dehors du destructeur)

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Classe pour la création d'un graphe xy
    Par Bob dans le forum MFC
    Réponses: 24
    Dernier message: 03/12/2009, 17h20
  2. problème classe utilisant le multiprocessing
    Par airod dans le forum Général Python
    Réponses: 2
    Dernier message: 14/11/2009, 11h29
  3. Réponses: 31
    Dernier message: 30/03/2006, 16h57
  4. Variable d'une Classe Ancêtre
    Par Génie dans le forum Langage
    Réponses: 3
    Dernier message: 18/09/2002, 19h24
  5. Sortir un typedef d'une classe
    Par Theophil dans le forum C++Builder
    Réponses: 13
    Dernier message: 03/07/2002, 17h21

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo