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

Calcul scientifique Python Discussion :

Gagner du temps sur moyennage


Sujet :

Calcul scientifique Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    36
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 36
    Par défaut Gagner du temps sur moyennage
    Bonjour bonjour,

    Voilà l'histoire : je suis en cours de finalisation d'un prog Python, et j'essaie entre autres de gagner du temps sur l'exécution.
    Or une fonction particulière de mon programme prend beaucoup de temps, et j'ose suputer qu'il existe un moyen détourné plus rapide d'arriver à mes fins!

    Voilà la bête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    import numarray as n
    
    def miseEchelle(entree, long, moy):
    
    sortie = list() for i in range(0, long, moy): sortie.append ( n.average ( entree[i:i + moy - 1] ) ) return n.array(sortie, 'Float32')
    Comme c'est écrit, le but de la fonction est de mettre à l'échelle une image. La fonction s'applique à une ligne de 15000, 20000, 40000 pixels, le pas de moyennage est en général de 30, et l'image compte 800 lignes... ce qui donne:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for i in range(800):
        # lecture d'une ligne
        ligne_moy = miseEchelle(ligne, 20000, 30)
        # ecriture de ligne_moy
    Tout est simplifié bien sûr. La boucle prend chez moi environ 100 s (j'utilise déjà psyco, et oui l'ordi est vieux!! ) et a priori à cause de average.

    Bon... quelqu'un est inspiré?

  2. #2
    Expert confirmé
    Avatar de Guigui_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2002
    Messages
    1 864
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2002
    Messages : 1 864
    Par défaut
    Quelques optimisations rapides:
    Toujours penser au variable locale quand on utilise une boucle for

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import numarray as n
     
    def miseEchelle(entree, long, moy):
        sortie = list()
        sortieappend = sortie.append
        naverage = n.average
        moy1 = moy-1
        for i in range(0, long, moy):
            sortieappend ( naverage ( entree[i:i + moy1] ) )     
        return n.array(sortie, 'Float32')

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    36
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 36
    Par défaut
    Oki
    J'teste ça demain, je donnerai les résultats en direct live.

    Mais je pensais que l'économie de variables était souvent importante... ça gêne pas d'en déclarer plein comme ça?

    ------
    Note : oui, ouiiiii, je ne suis pas très fort en prog... mais 'm'en sors quand même!

  4. #4
    Expert confirmé
    Avatar de Guigui_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2002
    Messages
    1 864
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2002
    Messages : 1 864
    Par défaut
    Citation Envoyé par Panthère Bleue
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for i in range(800):
        # lecture d'une ligne
        ligne_moy = miseEchelle(ligne, 20000, 30)
        # ecriture de ligne_moy
    Est-ce que ligne est modifié dans la boulce for parce que sinon, tu fais 800 fois la même chose (donc autant le sortir de la boucle) ?

    L'économie de variable peut être intéressante lorsque tu utilises des objets d'une même classe en grandes quantité (donc moins il possède d'attribut moins la place en mémoire sera importante). Sinon, cela n'a pas trop d'importance.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    36
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 36
    Par défaut
    Oui, oui... mais toutes ces réflexions me font penser que mon code est peut etre bien plus maladroit que je n'le pensais.

    La boucle ressemble plus à ça:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    flu = open('c:/fichier_a', 'rb')
    fecrit = open('c:/fichier_b', 'ab')
    
    for i in range(800):
        ecritureLigne( fecrit, miseEchelle( lectureLigne(flu), 20000, 30 ) )
    
    # fermeture de flu et fecrit.
    Pendant toute la boucle, les fichiers restent ouverts. Les lignes sont prises une à une, mises à l'échelle (en réalité, il y a 2 autres opérations avant la mise à l'échelle mais je simplifie...) puis écrites les unes à la suite des autres dans le fichier de sortie.

    Comme toutes les lignes de l'image sont distinctes, ligne est différent à chaque itération. C'est bien ça que tu demandais?... sinon, j'vais attendre demain, j'aurais les idées plus claires.

    Merci en tout cas de réfléchir avec moi là dessus, c'est instructif!

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    36
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 36
    Par défaut
    Alors j'ai fait plusieurs essais :
    a - en appliquant tes conseils,
    b - en utilisant psyco,
    c - en remplaçant average par un moyennage bidouillé

    Je calcule le temps d'exécution en enregistrant time.localtime() au début et à la fin et en soustrayant les 2. Les essais sont réalisés dans les mêmes conditions : aucune autre fenêtre ouverte que la console windows où le programme tourne.
    1. a : 162s
    2. a + b : 115s
    3. b : 121s
    4. a+c : 116s
    5. c: 115s
    6. b+c : 94s


    Bon, voilà. Ce n'est pas d'une précision folle, mais suffisante pour se rendre compte que average prend énormément de temps...
    En remplaçant:
    par:
    le résultat est identique. Mais le temps d'exécution est moins long dans le 2e cas... hum. Je vais aller étudier la méthode average, c'est vraiment bizarre.

  7. #7
    Membre émérite Avatar de pop_up
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    877
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2006
    Messages : 877
    Par défaut
    bonjour,

    trés interressante cette discussion.
    et sinon, a tu essayer de stocker tes lignes dans une variable et de ne faire que l'ouverture du fichier une fois le calcul terminé ?

    juste pour savoir car je ne suis pas sur que tu y gagnes du temps.

  8. #8
    Expert confirmé
    Avatar de Guigui_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2002
    Messages
    1 864
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2002
    Messages : 1 864
    Par défaut
    Citation Envoyé par Panthère Bleue
    le résultat est identique. Mais le temps d'exécution est moins long dans le 2e cas... hum. Je vais aller étudier la méthode average, c'est vraiment bizarre.
    Attention, average n'a pas été conçue pour faire des moyennes simples mais des moyennes quantifiées
    average(x, axis=0, weights=None, returned=0)
    Donc forcément, ce n'est pas optimisée pour ce que tu veux faire (et surtout si tu l'exécute beaucoup de fois)
    préfère alors la fonction mean() qui fait une moyenne simple et qui devrait être beaucoup plus rapide

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    import numarray as n
     
    def miseEchelle(entree, long, moy):
        sortie = list()
        sortieappend = sortie.append
        moy1 = moy-1
        for i in range(0, long, moy):
            sortieappend (entree[i:i + moy1].mean() )     
        return n.array(sortie, 'Float32')

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    36
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 36
    Par défaut
    pop_up, je n'ai pas essayé de stocker les données traitées avant d'ouvrir le fichier en écriture. Je ne suis pas sûr que ce soit vraiment bénéfique... mais là pour aujourd'hui j'ai un peu la flemme d'essayer.

    Guigui, j'ai tenté le coup avec mean() mais... les calculs sont plus lents qu'avec average!
    Pour des conditions identiques :
    1. mean : 130s
    2. average : 113s
    3. sum: 97s

    C'est vrai que average est prévu pour des moyennes pondérées, sur des tableaux multidimensionnels en plus, alors que je n'ai que des lignes.
    Pour mean, j'ai du mal à comprendre... la méthode se résume à prendre sum et à diviser par nelements.
    En prenant sum et en divisant par float(len()), comme je fais, c'est carrément plus rapide.
    Bah...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    import numarray as n
     
    def miseEchelle(entree, long, moy):
        sortie = list()
        for i in range(0, long, moy):
            sortie.append (sum(entree[i:i + moy - 1]) / float(moy) )     
        return n.array(sortie, 'Float32')
    Note : la déclaration des variables locales sortieappend et moy1 n'accélère pas toujours le calcul, parfois ça prend même 1s de plus...

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

Discussions similaires

  1. Réponses: 0
    Dernier message: 05/10/2014, 16h32
  2. Réponses: 4
    Dernier message: 06/11/2007, 23h31
  3. [VBA-E]Decompte de temps sur un userform
    Par alex_95 dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 25/04/2007, 15h49
  4. ecrire en meme temps sur un fichier
    Par LesLemmings dans le forum Visual C++
    Réponses: 5
    Dernier message: 11/04/2007, 14h50
  5. VBA-E gagner du temps d'execution
    Par bernard38 dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 24/10/2006, 09h50

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