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 :

Pourquoi ma boucle for est plus rapide que mon expression vectorisée ?


Sujet :

MATLAB

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    77
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 77
    Points : 30
    Points
    30
    Par défaut Pourquoi ma boucle for est plus rapide que mon expression vectorisée ?
    Bonjour,

    J'ai un code que j'ai vectorisé et qui est plus lent que le code avec les boucles for, et je trouve ça étrange. Pour 10000 répétitions du code la version boucle for met 0.74s d'exécution tandis que la version vectorisée en met 1.3s.


    Voici la version for:
    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
    %préallocation
    [N,~]=size(x1); 
    xPoint1=zeros(N,1);
    xPoint2=zeros(N,1);
     
     
    %conditions limites
    xPoint1(1)=x2(1);
    xPoint2(1)=-eta(1)/mu(1)*max(x1(1)-x1(2),0)^(3/2)-x1(1)/mu(1); 
     
    xPoint1(N)=x2(N);
    xPoint2(N)=eta(N-1)/mu(N)*max(x1(N-1)-x1(N),0)^(3/2)-x1(N)/mu(N);
     
    %cas général
    for n=2:N-1
        xPoint1(n)=x2(n);
        xPoint2(n)=eta(n-1)/mu(n)*max(x1(n-1)-x1(n),0)^(3/2)-eta(n)/mu(n)*max(x1(n)-x1(n+1),0)^(3/2)-x1(n)/mu(n);
    end

    et la version vectorisée: (désolé pour les longues expressions)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    xPoint1=x2;
    xPoint2=eta(1:end-1)./mu(2:end-1).*max(x1(1:end-2)-x1(2:end-1),0).^(3/2)-eta(2:end)./mu(2:end-1).*max(x1(2:end-1)-x1(3:end),0).^(3/2)-x1(2:end-1)./mu(2:end-1);
    xPoint2=[-eta(1)/mu(1)*max(x1(1)-x1(2),0)^(3/2)-x1(1)/mu(1);xPoint2;eta(end)/mu(end)*max(x1(end-1)-x1(end),0)^(3/2)-x1(end)/mu(end)];

    Merci pour votre aide.

  2. #2
    Modérateur

    Homme Profil pro
    Ingénieur en calculs scientifiques
    Inscrit en
    Août 2007
    Messages
    4 639
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Ingénieur en calculs scientifiques

    Informations forums :
    Inscription : Août 2007
    Messages : 4 639
    Points : 7 614
    Points
    7 614
    Par défaut
    Bonjour,

    comment as-tu comparé les 2 codes? Pour comparer correctement les temps d'exécution, il faut placer les 2 codes dans 2 fonctions différentes et calculer les temps d'exécution de ces deux fonctions.

    Tu fais 10000 répétitions du code, ou bien 10000 est l'ordre de grandeur de N?

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    77
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 77
    Points : 30
    Points
    30
    Par défaut
    Citation Envoyé par magelan Voir le message
    comment as-tu comparé les 2 codes? Pour comparer correctement les temps d'exécution, il faut placer les 2 codes dans 2 fonctions différentes et calculer les temps d'exécution de ces deux fonctions.
    C'est ça, sauf que j'ai fait un fichier script.

    Citation Envoyé par magelan Voir le message
    Tu fais 10000 répétitions du code
    oui (pour éviter d'avoir des temps trop petits)

  4. #4
    Modérateur

    Homme Profil pro
    Ingénieur en calculs scientifiques
    Inscrit en
    Août 2007
    Messages
    4 639
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Ingénieur en calculs scientifiques

    Informations forums :
    Inscription : Août 2007
    Messages : 4 639
    Points : 7 614
    Points
    7 614
    Par défaut
    Peux tu nous montrer le code complet que tu utilises?

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    77
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 77
    Points : 30
    Points
    30
    Par défaut
    Citation Envoyé par magelan Voir le message
    Peux tu nous montrer le code complet que tu utilises?
    Voici:

    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
    x1=x0(1:2:end,:);
    x2=x0(2:2:end,:);
     
     
    tic
    for i=1:10000
        %préallocation
        [N,~]=size(x1);
        xPoint1=zeros(N,1);
        xPoint2=zeros(N,1);
     
     
        %conditions limites
        xPoint1(1)=x2(1);
        xPoint2(1)=-eta(1)/mu(1)*max(x1(1)-x1(2),0)^(3/2)-x1(1)/mu(1);
     
        xPoint1(N)=x2(N);
        xPoint2(N)=eta(N-1)/mu(N)*max(x1(N-1)-x1(N),0)^(3/2)-x1(N)/mu(N);
     
        %cas général
        for n=2:N-1
            xPoint1(n)=x2(n);
            xPoint2(n)=eta(n-1)/mu(n)*max(x1(n-1)-x1(n),0)^(3/2)-eta(n)/mu(n)*max(x1(n)-x1(n+1),0)^(3/2)-x1(n)/mu(n);
        end
    end
    toc
     
     
    tic
    for i=1:10000
        xPoint1=x2;
        xPoint2=eta(1:end-1)./mu(2:end-1).*max(x1(1:end-2)-x1(2:end-1),0).^(3/2)-eta(2:end)./mu(2:end-1).*max(x1(2:end-1)-x1(3:end),0).^(3/2)-x1(2:end-1)./mu(2:end-1);
        xPoint2=[-eta(1)/mu(1)*max(x1(1)-x1(2),0)^(3/2)-x1(1)/mu(1);xPoint2;eta(end)/mu(end)*max(x1(end-1)-x1(end),0)^(3/2)-x1(end)/mu(end)];
    end
    toc

  6. #6
    Modérateur

    Homme Profil pro
    Ingénieur en calculs scientifiques
    Inscrit en
    Août 2007
    Messages
    4 639
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Ingénieur en calculs scientifiques

    Informations forums :
    Inscription : Août 2007
    Messages : 4 639
    Points : 7 614
    Points
    7 614
    Par défaut
    Et bien justement, ce n'est pas ce que j'ai dit: il faut que tes 2 codes soient dans 2 fonctions différentes et qu'elles soient appelés l'une après l'autre.

    Quelque chose comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    x1=x0(1:2:end,:);
    x2=x0(2:2:end,:);
     
     
    tic
    fonction1(x1,x2)
    toc
     
     
    tic
    fonction2(x1,x2)
    toc
    Sinon, l'exécution du premier code influence la durée d'exécution du second.

    De plus tu utilises la vectorisation pour supprimer une boucle for, et pour tester son efficacité, tu rajoutes une boucle for Du coup je ne suis pas sûr qu'il y est un gain de temps entre les méthodes. L'avantage de la vectorisation est visible lorsque la dimension des variables augmentent.

  7. #7
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    77
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 77
    Points : 30
    Points
    30
    Par défaut
    Citation Envoyé par magelan Voir le message
    Sinon, l'exécution du premier code influence la durée d'exécution du second.
    J'avoue que je vois pas pourquoi.


    Mais en fait le code que j'ai montré est le second membre d'une équa diff. Et est donc dans une fonction. Equa diff que je résous en appelant cette fonction dans ode45.
    Lorsque l'ordi met environ 5min à résoudre l'équa diff. Et bien je gagne 5sec si dans ma fonction j'utilise la boucle for plutôt que l'équation vectorielle.

    Citation Envoyé par magelan Voir le message
    De plus tu utilises la vectorisation pour supprimer une boucle for, et pour tester son efficacité, tu rajoutes une boucle for
    Oui c'est vrai ça sert à rien car le temps augmente linéairement en fonction du tour de boucle. Avec cette méthode je pensais être plus précis, par contre ça n'influe pas sur la différence de temps.


    Citation Envoyé par magelan Voir le message
    L'avantage de la vectorisation est visible lorsque la dimension des variables augmentent.
    C'est le cas mes vecteurs sont grands.

  8. #8
    Rédacteur/Modérateur

    Avatar de Jerome Briot
    Homme Profil pro
    Freelance mécatronique - Conseil, conception et formation
    Inscrit en
    Novembre 2006
    Messages
    20 313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Freelance mécatronique - Conseil, conception et formation

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20 313
    Points : 52 939
    Points
    52 939
    Par défaut
    Citation Envoyé par magelan Voir le message
    Quelque chose comme :
    Plus précisément :

    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
     
    x0 = ...;
    x1 = x0(1:2:end,:);
    x2 = x0(2:2:end,:);
     
    for n = 1:10
        tic
        fonction1(x1,x2)
        t(n) = toc;
    end
    mean(t)
     
    clear all
     
    x0 = ...;
    x1 = x0(1:2:end,:);
    x2 = x0(2:2:end,:);
     
    for n = 1:10
        tic
        fonction2(x1,x2)
        t(n) = toc;
    end
    mean(t)
    Note au passage que si les valeurs de x1 et de x2 ne sont pas modifiées par les fonctions fonction1 et fonction2, il est préférable de passer uniquement le vecteur x0 et d'utiliser les indices correspondant précédemment à x1 et x2 dans les fonctions.

  9. #9
    Membre éprouvé
    Avatar de ol9245
    Homme Profil pro
    Chercheur
    Inscrit en
    Avril 2007
    Messages
    985
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Avril 2007
    Messages : 985
    Points : 1 158
    Points
    1 158
    Billets dans le blog
    1
    Par défaut
    En effet, c'est un contre-exemple étonnant du dogme Matlab !

    C'est probablement le calcul de tes indices qui plante la # dans ton code vectorisé.
    A chaque appel de vecteur tu recalcule une brouettée d'indices 1:end-1, 2:end, blablabla. et tu vas rééchantillonner dans tes vecteur sur les indices que tu viens de calculer. C'est lourd !

    Optimise pour éviter l'utilisation de ces indices et ça ira mieux.

    Si le temps est important pour toi, regarde du côté des fonctions circshift (sans garantie je n'ai jamais utilisé). ou bien reformuler ton problème pour accélérer cela.

    Par ailleurs il y a des parties de ton code qui m'intriguent. je te suggère de vérifier une bonne fois que tes matrices calculées par l'une ou l'autre manière sont identiques. à vue d'oeuil, je n'en mettrais pas ma main au feu...

Discussions similaires

  1. Est-ce qu'une jointure avec JOIN est plus rapide que via le WHERE ?
    Par clavier12AZQSWX dans le forum PostgreSQL
    Réponses: 7
    Dernier message: 13/01/2014, 16h31
  2. multipathd et oracleasm : l'un est plus rapide que l'autre
    Par exanlb dans le forum Administration
    Réponses: 0
    Dernier message: 04/04/2012, 15h54
  3. Réponses: 4
    Dernier message: 04/06/2009, 09h51
  4. Pourquoi mon code est plus lent que Arrays.sort
    Par alexis779 dans le forum Collection et Stream
    Réponses: 3
    Dernier message: 12/12/2006, 12h44

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