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

MATLAB Discussion :

Améliorer l'exécution d'un boucle


Sujet :

MATLAB

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 14
    Points : 9
    Points
    9
    Par défaut Améliorer l'exécution d'un boucle
    Bonjour,
    J'ai écrit une boucle de 1 à 10000. Mais le temps d’exécution du programme est énorme .
    Mon programme (pour le calcul de la markovienne ) est le suivant:
    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
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    tic();
    Mark11=sparse(debL:finL,1:10000,0);
    Mark12=sparse(debL:finL,10001:20000,0);
    Mark13=sparse(debL:finL,20001:30000,0);
    Mark14=sparse(debL:finL,30001:40000,0);
    Mark15=sparse(debL:finL,40001:50000,0);
    Mark16=sparse(debL:finL,50001:60000,0);
    for m = debL:20
        disp(m);
        SB = sum(A11,2);
        for p= 1:10000,
            Mark11(m,p) = A11(m,p)/SB(m);
        end
     
        SB = sum(A12,2);
        for p = 10001:20000
            Mark12(m,p) = A12(m,p)/SB(m);
        end
     
        SB = sum(A13,2);
        for p = 20001:30000
            Mark13(m,p)= A13(m,p)/SB(m);
        end
        %clear SB ;
        SB = sum(A14,2);
        for p = 30001:40000
            Mark14(m,p)= A14(m,p)/SB(m);
        end
     
        SB = sum(A15,2);
        for p = 40001:50000
            Mark15(m,p)= A15(m,p)/SB(m);
        end
     
        SB = sum(A16,2);
        for p = 50001:60000
            Mark16(m,p)= A16(m,p)/SB(m);
        end
    end
    toc();
    Je cherche à améliorer le temps d'exécution. J'ai essayé avec parfor, mais j'ai pas eu de très bons résultats.
    Je vous remercie.

  2. #2
    Expert confirmé
    Avatar de duf42
    Homme Profil pro
    Formateur en informatique
    Inscrit en
    Novembre 2007
    Messages
    3 111
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Formateur en informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 111
    Points : 4 661
    Points
    4 661
    Par défaut
    Bonjour,

    Rapidement, tu peux déjà sortir tes sommes de la boucle puisqu'elles n'en dépendent pas. Et aussi supprimer les boucles imbriquées (ainsi que le DISP):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    SB1 = sum(A11,2);
    SB2 = sum(A12,2);
    ...
    for m = debL:20
        Mark11(m,1:10000) = A11(m,1:10000)/SB1(m);
        Mark12(m,10001:20000) = A12(m,10001:20000)/SB2(m);
        ...
    end
    Duf
    Simulink & Embedded Coder

    Au boulot : Windows 7 , MATLAB r2016b
    A la maison : ArchLinux mais pas MATLAB

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 14
    Points : 9
    Points
    9
    Par défaut
    Merci beaucoup ça m'a bcp aidé

  4. #4
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    Ton problème principal c'est que tes lignes SB = sum(Axx,2); sont constantes et n'ont pas leur place dans ta boucle, et surtout que tu refais le calcul à chaque itération!!!
    Une première solution serait de faire plusieurs boucle for comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SB = sum(A11,2);
    for m = debL:finL
        Mark11(m,1:10000) = A11(m,1:10000)/SB(m);
    end
    Une deuxième solution sans boucle serait d'utiliser la fonction doc bsxfun pour tes lignes Markxx(m,1:10000) = Axx(m,1:10000)/SB(m);.

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 14
    Points : 9
    Points
    9
    Par défaut
    Bonjour,
    J'ai modifié le code de la manière que vous m'avez suggérez.
    Il est devenu donc (j'ai besoin de 10000 itérations càd : debL=1 et finL=10000 )
    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
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    function[Mark11,Mark12,Mark13,Mark14,Mark15,Mark16] = markov(debL,finL,A11,A12,A13,A14,A15,A16)
    %calcul de la matrice markovienne.
    Mark11=sparse(debL:finL,1:10000,0);
    Mark12=sparse(debL:finL,10001:20000,0);
    Mark13=sparse(debL:finL,20001:30000,0);
    Mark14=sparse(debL:finL,30001:40000,0);
    Mark15=sparse(debL:finL,40001:50000,0);
    Mark16=sparse(debL:finL,50001:60000,0);
     
    SB1 = sum(A11,2);
    SB2 = sum(A12,2);
    SB3 = sum(A13,2);
    SB4 = sum(A14,2);
     SB5 = sum(A15,2);
      SB6 = sum(A16,2);
      tic();
    for m = debL:finL
        disp(m);
     
        Mark11(m,1:10000) = A11(m,1:10000)/SB1(m);
     
        Mark12(m,10001:20000) = A12(m,10001:20000)/SB2(m);
     
        Mark13(m,20001:30000)= A13(m,20001:30000)/SB3(m);
        Mark14( m,30001:40000)= A14( m,30001:40000)/SB4(m);
        Mark15(m,40001:50000)= A15(m,40001:50000)/SB5(m);
        Mark16(m,50001:60000)= A16(m,50001:60000)/SB6(m);
     
    end
     
    toc();
     
    end
    Les premières itérations se produisent rapidement ( une dizaine )
    Mais après , l'exécution devient très lente au point que pendant 2 heures uniquement 200 itérations ont été effectuées. Donc pour 1000 il me faudra 10 heures , et pour les 10000 il me faudra 100 heures!!!!!!!!!!!
    Comment dois je faire ?

    Codialement
    Asma

  6. #6
    Membre habitué
    Homme Profil pro
    Ingénieur opto-électronique
    Inscrit en
    Avril 2010
    Messages
    129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur opto-électronique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2010
    Messages : 129
    Points : 157
    Points
    157
    Par défaut
    Je dis peut-être une bêtise, mais est-il vraiment nécessaire de faire une boucle pour calculer tout ça ? Ne pourrais tu pas directement faire une division élément par élément de tes matrices A11, A12, ... par SB1, SB2..., éventuellement avec un repmat(SB1,...) pour que les dimensions concordent ? Il me semble que c'est faisable et que ça t'éviterait d'effectuer 10 000 fois la même opération.

Discussions similaires

  1. ShowMessage qui modifie l'exécution d'une boucle
    Par OutOfRange dans le forum Langage
    Réponses: 11
    Dernier message: 14/07/2009, 01h45
  2. Réponses: 1
    Dernier message: 06/05/2008, 13h32
  3. Afficher un waitbar pendant l'exécution d'une boucle while
    Par LMU2S dans le forum Interfaces Graphiques
    Réponses: 1
    Dernier message: 18/03/2008, 19h22
  4. Amélioration temps exécution update
    Par angebe dans le forum SQL
    Réponses: 17
    Dernier message: 14/01/2008, 08h28
  5. [Système] problème d'exécution d'une boucle
    Par WalidNat dans le forum Langage
    Réponses: 6
    Dernier message: 02/04/2006, 00h55

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