Forum Programmation.python generateur et performances

Posté par  . Licence CC By‑SA.
Étiquettes : aucune
2
26
oct.
2020

bonjour,
je m'interroge sur la pertinence d'utiliser un generateur pour gagner en performance.

en l'occurence, j'ai un fichier csv sur lequel je souhaite faire des calculs.
actuellement je fais :

def fonction1(csv):
    result=[]
    fi=open(csv,r)
    listing=fi.readlines()
    for i in listing:
        i.strip('\n')
        ic=calcul sur i
        result.append(ic)
    fi.close()
    return result

avec un generateur, je pourrais faire :

def generateur(csv):
    fi=open(csv,r)
    NumberOfLine = 0
    for line in fi:
        NumberOfLine += 1
    fi.seek(0)
    for i in NumberOfLine:
        yield fi.readline()
    fi.close()
def fonction2(csv):
    result=[]
    for j in generateur(csv):
        j.strip('\n')
        jc=calcul sur j
        result.append(jc)
    return result

est ce qu'en faisant ainsi je gagnerais en performance?

  • # non

    Posté par  (site Web personnel) . Évalué à 4 (+2/-0).

    Je ne suis pas le plus grand spécialiste de python mais moi je dirais "non", parce que :

    1/ tu lis 2 fois le fichier (modulo je ne vois pas comment tu peux iterer sur NumberOfLine qui est un chiffre)
    2/ l'itérateur n'accélère pas le code si tu iter la totalité de ton fichier dans tous les cas avant de retourner le résultat.

    PS: il y a une bibliothèque pour lire le csv : https://docs.python.org/3/library/csv.html

    • [^] # Re: non

      Posté par  . Évalué à 1 (+0/-0).

      1/ oui désolé cest for i in range(NumberOfLine)
      2/ si je retourne le resultat à chaque ligne, réécrire tout le fichier de resultat prendrait bcp de temps il me semble..

      les csv sont assez conséquent (centaines de Mo) et en fait quand je lance mes algorithmes, meme sur une machine peu performante, le% de cpu et de ram utilisé reste en dessous de 50%.
      D'apres ce que je vois sur internet, les threads et calculs paralelles en python permettent d accelerer les entree/sortie.
      On m'a conseillé dans un autre post du forum d'utiliser les iterateurs/generateurs. Mais je ne vois pas trop l'interet en termes de performance de réecrire tous le fichier de resultats a chaque ligne calculée (hormis pour sauvegarder au fur et a mesure pour eviter de perdre les resultats en cas de plantage).

      • [^] # Re: non

        Posté par  (site Web personnel) . Évalué à 4 (+3/-0).

        Ton pointeur de fichier fait déjà ça, non ?

        with open('miaou.csv') as fp:
            for line in fp:
                print(line)

        Debian Consultant @ DEBAMAX

        • [^] # Re: non

          Posté par  . Évalué à 4 (+3/-0).

          Tout à fait d'accord : la classe File de python propose déjà un itérateur, autant l'utiliser.

          En pratique, il ne faut pas attendre de vrai gain sur le temps d'exécution, les opérations faites sur chaque ligne étant probablement plus lentes que la lecture d'une ligne du fichier.

          Là où tu gagnes, c'est en mémoire vu que tu ne stockes pas en mémoire une liste ayant potentiellement un grand nombre de chaines de caractères (soit en mémoire la taille des fichiers éventuellement décompressés).
          Avec les itérateurs (et les générateurs en général), tu n'aurais en mémoire que ton objet result et une seule ligne du fichier.

          • [^] # Re: non

            Posté par  (site Web personnel) . Évalué à 2 (+0/-0). Dernière modification le 27/10/20 à 07:49.

            « [L]es csv sont assez conséquents et en fait quand je lance mes algorithmes, m[ê]me sur une machine peu performante, le % de cpu et de ram utilisé reste en dessous de 50%. »

            Je me demande quel pourrait bien être l'intérêt de gagner de la mémoire qui se compterait en quelques centaines de mégaoctets sur une machine moderne ?

            Si le cpu est peu utilisé, n'est-il pas vraisemblable que les opérations sur chaque ligne du fichier soient très légères et que le temps d’exécution du programme soit majoritairement consacré à la lecture/écriture des fichiers ? Dans ce cas là, ne conseillerait-on pas de lire d'un coup une quantité confortable de données, par exemple 100Mo, de les traiter, puis d'écrire d'un coup le résultat ; et de recommencer.

            « IRAFURORBREVISESTANIMUMREGEQUINISIPARETIMPERAT » — Odes — Horace

            • [^] # Re: non

              Posté par  (site Web personnel) . Évalué à 2 (+0/-0). Dernière modification le 27/10/20 à 14:23.

              Tout ça est passionnant je trouve :)

              La solution de Cyril est surtout très élégante.

              Personnellement je ferais le pari que les performances seront naturellement au rendez-vous.

              Il y a énormément d’optimisations à différents niveaux quant aux lectures écriture dans la mémoire de masse (comme nous disions jadis :)

              Nous attendons les mises à l’épreuve et comparatifs de performances des différentes solutions :)

      • [^] # Re: non

        Posté par  . Évalué à 4 (+2/-0). Dernière modification le 27/10/20 à 09:15.

        Comme dit un peu plus récemment, au lieu de lire le fichier ligne par ligne, il faut en charger une partie et faire les opérations sur ce morceau.
        Fait des recherches data chunk python pandas. Pandas est une bibliothèque pour manipuler les données en python.

        • [^] # Re: non

          Posté par  . Évalué à 1 (+0/-0).

          ok, dans mon exemple, je charge tout le fichier et je fais ensuite des opérations ligne par ligne, ce qui ne semble pas vraiment pertinent a priori.
          Ce que vous mentionnez ressemble à de la gestion de buffers dans certains logiciels que j'ai utilisé pour traiter de grandes quantités de données, mais ca me semble un peu compliqué sans utiliser des librairies externes comme panda..

        • [^] # Re: non

          Posté par  . Évalué à 1 (+0/-0).

          Pour info la fonction open en python prend un argument buffering qui détermine la taille des pages (chunks) à charger, donc pas besoin de pandas pour ça. Sinon je confirme que la lecture des csv avec pandas est rapide, bien plus que son équivalent numpy.

  • # processus en serie et temps d'execution

    Posté par  . Évalué à 1 (+0/-0).

    Une question subsidiaire:
    si j'ai un bouton dans un module tk qui fait 3 commandes mais que la 1ere prend 2h à s exécuter, qu'en est il des deux autres? est ce que python ne risque pas de buguer vu le temps d execution de la 1ere commande et ne pas executer les deux suivantes?

    • [^] # Re: processus en serie et temps d'execution

      Posté par  . Évalué à 2 (+0/-0).

      Je n'ai pas épluché TK mais si un bouton a un timeout d'exécution, il ne sera clairement pas de une heure, surement plutôt de quelques secondes. Donc si la première commande passe, je ne me ferai pas de soucis pour les autres.

      En revanche, je me demande ce qui peut prendre autant de temps. Un pc classique peut faire tellement de choses en 3600 secondes.

      • [^] # Re: processus en serie et temps d'execution

        Posté par  . Évalué à 1 (+0/-0).

        cest sur une cle linux live persistent ca ralentit bcp les temps d acces aux fichiers. les fichiers sont des fichiers openstreetmap qui contiennent beaucoup de données spatiales..

Envoyer un commentaire

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n’en sommes pas responsables.