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 :

Processus asynchrone et processus parallèle [Python 3.X]


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de FadeToBlack
    Homme Profil pro
    ...
    Inscrit en
    Août 2010
    Messages
    321
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : ...
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Août 2010
    Messages : 321
    Par défaut Processus asynchrone et processus parallèle
    Bonjour à tous,

    Je crée ce post parce que je n'arrive pas à comprendre, sans doute une notion de base, la différence entre l'asynchrone et le parallèlisme.

    Pour le moment, je n'ai pas de problème de code à rédiger, je verrais cela plus tard. Il s'agit des concepts que je n'arrive pas à comprendre.

    Mais pour une question de compréhension, je vais essayer de prendre un exemple précis. Exemple idiot mais je n'ai rien trouver de mieux.

    Disons que j'ai un répertoire "Rep_A" qui contient des sous-répertoires, et des fichiers. Disons plusieurs dizaines de milliers de fichiers.

    Un répertoire "Rep_B" qui possède une arborescence différentes avec aussi plusieurs dizaines de milliers de fichiers.

    Problématique :
    Je veux faire la liste de mes fichiers dans "Rep_A" et vérifier s'ils existent dans "Rep_B", et vérifier qu'ils sont identiques.
    Si oui, écrire dans un fichier Same.txt, le nom et chemin du fichier identique (dans Rep_A)
    Si non, écrire dans un fichier different.txt le nom et chemin du fichier dans (Rep_A).



    Je suppose que prendre le premier fichier de Rep_A, faire la recherche dans Rep_B, comparer les deux fichiers, puis écrire dans un des deux txt, puis faire de même pour le second fichier etc..... va prendre beaucoup de temps.

    Je me suis dis qu'il serait peut-être intéressant de lancer plusieurs tâche de recherche et de comparaison en parallèle. Histoire de profiter de toute ma Ram et de mes multicore.


    Comment appréhender ce problème avec du parallèlisme ou de l'asynchrone. Quelles sont les différences entre les deux ?.


    Je vous remercie de votre aide.

    Boonne journée à tous.

  2. #2
    Membre expérimenté Avatar de zancrows
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2016
    Messages
    159
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2016
    Messages : 159
    Par défaut
    Bonjour,

    si tu n'es pas déjà tombé dessus tu devrais faire un tour ici --> http://sametmax.com/la-difference-en...t-concurrente/
    il explique de manière simple la programmation asynchrone, parallèle et concurrente.

  3. #3
    Membre éclairé Avatar de FadeToBlack
    Homme Profil pro
    ...
    Inscrit en
    Août 2010
    Messages
    321
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : ...
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Août 2010
    Messages : 321
    Par défaut
    merci Zancrows,

    j'avais effectivement vu cet article. Mais c'est à la lecture de ce post (un peu vieux me semble-t-il car avant la 3.5) que me viennent mes troubles.

    Comment déterminer quels orientations prendre dans mon cas d'étude . C'est à ce niveau là que je ne comprends pas. C'est aussi peut être que je n'ai pas compris l'article......

  4. #4
    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,

    Je suis loin d'être un spécialiste de ces questions, mais par expérience, on peut lancer plusieurs tâches qui s'exécuteront en même temps dans des cœurs différents du microprocesseur. Pour faire ça, on peut utiliser le module "multiprocessing" ou "concurrent.futures".

    Mais si l'un des processus a besoin des résultats de l'autre, c'est ton cas, ça se gâte un peu puisqu'il faut assurer une synchronisation entre les 2! On peut le faire avec l'accès (contrôlé!) à des variables communes que chaque processus peut lire et modifier. J'utilise couramment pour ça de variables "multiprocessing.Queue()".

    Pire encore, si en permanence pour chaque fichier de Rep_A, tu as besoin de connaître tous les fichiers de Rep_B pour chercher, je ne vois aucun intérêt à vouloir faire des opérations en même temps!

    Il ne te reste alors qu'à travailler l'algorithme pour que la réponse se fasse dans un temps acceptable... Par exemple, une fois les fichiers de Rep_B trouvés, on peut construire un dictionnaire avec comme clés les noms de fichiers et comme valeur la liste des adresses-disque (le répertoire avec son chemin) dans lesquelles on trouve chacun des noms. Une fois ce dictionnaire créé, la recherche est très rapide puisque les clés sont "hashées". Il ne restera plus qu'à vérifier que ces fichiers portant le même nom ont bien le même contenu.

    Ça, c'est pour le principe, mais ça dépend aussi de ton contexte. Par exemple si tu dois faire d'autres choses avant avec ton programme, tu peux lancer la recherche des fichiers de Rep_B dans un processus différent afin d'être prêt plus rapidement pour la future recherche Rep_A <=> Rep_B. Bref, il faut réfléchir un peu à l'utilisation réelle de ton programme pour choisir la bonne solution.

  5. #5
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 754
    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 754
    Par défaut
    Salut,

    Citation Envoyé par tyrtamos Voir le message
    Mais si l'un des processus a besoin des résultats de l'autre, c'est ton cas, ça se gâte un peu puisqu'il faut assurer une synchronisation entre les 2! On peut le faire avec l'accès (contrôlé!) à des variables communes que chaque processus peut lire et modifier. J'utilise couramment pour ça de variables "multiprocessing.Queue()".
    Techniquement, c'est du pipelining qui est une variante du parallélisme.
    Mais pour votre code, çà serait mieux d'avoir une version qui fonctionne avant d'essayer de l'accélérer en parallélisant tout ou partie des traitements.
    note: un version qui fonctionne, c'est coder les opérations de bases. "paralléliser", ce sera ajouter du code pour que ces traitements communiquent via multiprocessing ou threads.

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

  6. #6
    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

    Citation Envoyé par wiztricks Voir le message
    Techniquement, c'est du pipelining qui est une variante du parallélisme.
    Merci pour l'info! J'ai prudemment évité de rentrer dans la typologie des méthodes...

    Citation Envoyé par tyrtamos Voir le message
    Par exemple, une fois les fichiers de Rep_B trouvés, on peut construire un dictionnaire avec comme clés les noms de fichiers et comme valeur la liste des adresses-disque (le répertoire avec son chemin) dans lesquelles on trouve chacun des noms. Une fois ce dictionnaire créé, la recherche est très rapide puisque les clés sont "hashées". Il ne restera plus qu'à vérifier que ces fichiers portant le même nom ont bien le même contenu.
    Je complète ma réponse précédente.

    Voilà une petite fonction qui va analyser le répertoire Rep_B pour retourner un dictionnaire des noms de fichiers avec la liste des répertoires contenant chacun de ces fichiers:

    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
    def trouvefichiersdico(repertoire, dicofics={}):
        """Trouve tous les fichiers du répertoire donné et de son arborescence.
           Retourne un dictionnaire dont les clés sont les noms de fichier
           et les valeurs sont la liste des répertoires contenant chaque fichier.
           erreurs est la liste des messages d'erreur rencontrés.
        """
        erreurs = []
        try:
            for entree in os.scandir(repertoire):
                if entree.is_file(follow_symlinks=False):
                    if entree.name in dicofics:
                        dicofics[entree.name].append(repertoire)
                    else:
                        dicofics[entree.name] = [repertoire]    
                elif entree.is_dir(follow_symlinks=False):
                    dicofics, errs = trouvefichiersdico(entree.path, dicofics)
                    erreurs += errs
        except Exception as msgerr:
            erreurs.append(msgerr)
        return dicofics, erreurs
    Si je prends pour exemple mon répertoire Python de 1,10 Go qui contient 40365 Fichiers et 4118 Dossiers (j'ai beaucoup de modules externes d'installés):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    repertoire = r"E:\Programmes\Python35"
    dicofics, erreurs, nbreps = trouvefichiersdico(repertoire)
    Il ressort que s'il y a 40365 fichiers, il n'y a que 26781 noms de fichiers différents dans les 4118 sous-répertoires.
    A l'affichage du dictionnaire, on va trouver par exemple, pour le nom de fichier "image.py":

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    images.py
    ===> E:\Programmes\Python35\Lib\site-packages\docutils\parsers\rst\directives
    ===> E:\Programmes\Python35\Lib\site-packages\OpenGL\GL
    ===> E:\Programmes\Python35\Lib\site-packages\OpenGL
    ===> E:\Programmes\Python35\Lib\site-packages\sphinx\transforms\post_transforms
    ===> E:\Programmes\Python35\Lib\site-packages\sphinx\util
    ===> E:\Programmes\Python35\Lib\site-packages\wx\lib\editor
    ===> E:\Programmes\Python35\Lib\site-packages\wx\lib\pdfviewer
    ===> E:\Programmes\Python35\Lib\site-packages\wx\py
    La réponse à la question <le fichier "image.py" de Rep_A existe-t-il dans Rep_B> sera facile:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    fichier = "images.py"
    print("Recherche du fichier", fichier)
    if fichier in dicofics:
        print("Trouvé dans le(s) répertoire(s):)
        for rep in dicofics[fichier]:
            print("===>", rep)
    else:
        print("Non trouvé")
    L'exécution est assez rapide: pour ce répertoire de plus de 40000 fichiers, cela prend quelques petites secondes au plus (0.5 seconde chez moi)

    Pour l'exploration du répertoire Rep_A, on peut proposer une autre fonction qui, elle, va retourner la liste complète de tous les fichiers du répertoire avec leur chemin:

    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
    def trouvefichiers(repertoire, listefics=[], nbreps=0):
        """Trouve tous les fichiers du répertoire donné et de son arborescence.
           Retourne une liste de ces fichiers avec leur chemin
           erreurs est la liste des messages d'erreur rencontrés.
        """
        erreurs = []
        nbreps += 1
        try:
            for entree in os.scandir(repertoire):
                if entree.is_file(follow_symlinks=False):
                    listefics.append(entree.path)
                elif entree.is_dir(follow_symlinks=False):
                    listefics, errs, nbreps = trouvefichiers(entree.path, listefics, nbreps)
                    erreurs += errs
        except Exception as msgerr:
            erreurs.append(msgerr)
        return listefics, erreurs, nbreps
    Il suffira donc pour résoudre le problème posé (si je l'ai bien compris):

    - de calculer le dictionnaire des fichiers de Rep_B
    - de calculer la liste des fichiers de Rep_A
    - de prendre dans une boucle tous les fichiers de la liste (Rep_A) et de comparer avec le dictionnaire (Rep_B)
    - au cas ou le nom de fichier se retrouve bien dans les 2 arborescences, et pour tous les sous-répertoires concernés, on peut comparer les tailles (os.path.getsize), les dates de dernière modif (os.path.getmtime), voire faire une comparaison binaire entre les 2 contenus.

    On peut trouver utile de faire chacun des 2 calculs (concernant Rep_A et Rep_B) dans 2 processus simultanés (multiprocessing.Process) dans 2 cœurs différents du microprocesseur, mais il faudra attendre que les 2 soient terminés pour commencer les recherches.

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

Discussions similaires

  1. conception et technologie d'un processus asynchrone
    Par Dr. Fioko dans le forum Développement Web en Java
    Réponses: 0
    Dernier message: 16/03/2017, 11h11
  2. fork processus zombie et processus orphelin
    Par TuxThePenguin dans le forum C
    Réponses: 16
    Dernier message: 05/10/2015, 20h28
  3. Réponses: 2
    Dernier message: 27/08/2012, 09h17
  4. Processus père attend processus fils
    Par prgasp77 dans le forum Administration système
    Réponses: 12
    Dernier message: 10/09/2009, 15h00

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