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

Traitement d'images Discussion :

Uniformisation de couleurs dans un dégradé : comment faire ?


Sujet :

Traitement d'images

  1. #121
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 720
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 720
    Points : 15 106
    Points
    15 106
    Par défaut
    Salutations distinguées,

    Citation Envoyé par wiwaxia Voir le message
    Citation Envoyé par anapurna
    dans le calcul de calcMat_002
    je vois que tu refais 3 fois le calcul
    Il n'y a plus d'expression de ce type dans le dernier programme envoyé - les graphes ont été supprimés.
    Je n'ai rien retrouvé de tel dans les versions précédentes, et cela m'aurait un peu étonné - mais tout le monde peut se tromper.
    Dans la procédure CalcMat_Im01 l'instruction
    se répète pour chacun des 3 graphes, par la force des choses; la variante que tu indiques ne vient pas de moi.
    Pour répondre à wiwaxia, ça doit être des bidouilles à moi, ça.
    Et pour répondre à anapurna : impossible d'utiliser une variable pour éliminer l'addition car y change avant l'addition en fonction de s.
    En gros ça ressemble à ça, dans une boucle For... 3 instructions par ligne, si tu mets 1 instruction par ligne tu verras que ton plan ne tient plus (les noms de variables changent mais le principe reste) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
          s:= iCoef_C(Pilote, r);     y:= Round(K1 * s); Ma[x, H1 - y]:= Cro;
          s:= iCoef_C(Pilote, r - h); y:= Round(K1 * s); Ma[x, H1 - y]:= Cve;
          s:= iCoef_C(Pilote, r + h); y:= Round(K1 * s); Ma[x, H1 - y]:= Cbl;
    Sinon je te rassure, je suis un grand amateur de ce genre d'optimisation, je me suis même inventé, pour ce programme, une variable nommée LargeurMoinsUn, si si !, qui me permet de faire des boucles genre for i := 0 to LargeurMoinsUn do..., et oui !

    Bonne journée,
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  2. #122
    Membre émérite

    Homme Profil pro
    Formation: Chimie et Physique (structure de la matière)
    Inscrit en
    Décembre 2010
    Messages
    1 333
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 77
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Formation: Chimie et Physique (structure de la matière)
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 333
    Points : 2 570
    Points
    2 570
    Billets dans le blog
    9
    Par défaut Il faut savoir de quoi on parle.
    Citation Envoyé par foetus Voir le message
    Citation Envoyé par wiwaxia
    l'instruction la plus concise n'est pas forcément souhaitable.
    Bien si ... mais il faut savoir de quoi on parle ...
    La correction proposée par anapurna est juste, astucieuse et acceptable; mais on aborde ici le procédé d'emboîtement des fonctions à seuil, qui conduit rapidement à des consignes peu intelligibles et difficilement contrôlables. Je me suis déjà exprimé là-dessus.
    Par ailleurs une procédure personnelle est préférable à l'imbrication forcenée de fonctions prédéfinies, parfois mal adaptées à ce que l'on veut faire.

    # Tu propose ensuite ensuite une procédure corrective CLAMP_0_1(VALUE) qui remplace deux instructions conditionnelles: où est l'avantage ? En quoi est-ce plus bref ? Le bornage n'intervient qu'une seule fois lors de l'appel de la fonction dans un bloc relativement court (10 lignes, délimiteurs compris !)..
    Dans le cas contraire, j'aurais tout regroupé dans une procédure du genre Bornage(a, b: Reel; VAR x: Reel).

    #
    Et si on travaille avec des entiers non signés, on n'a pas besoin du "test inférieur à zéro"
    Et où vois-tu un tel test imposé à des entiers de type byte ou word ?
    Il s'agit ici d'un fonction réelle d'une variable réelle initialement définie sur [-1 ; +1].
    Dans un débat, il n'est nullement interdit de se montrer intelligent ...

    #
    Par contre dans ce cas, il faudra sûrement revoir ses algos pour faire des translations pour éviter les intervalles négatifs
    Ah oui, bonne idée:
    a) si l'on se limite au domaine (t >= 0), la parité de la première fonction n'intervient plus, et l'on perd une simplification essentielle du calcul;
    b) il faut la définir sur [0 ; 2], l'extension du domaine imposant de nouvelles instructions conditionnelles. Tu y a sans doute pensé ?

    Comme tu l'a dit dès le début: il faut savoir de quoi on parle.


    Le français, notre affaire à tous
    Grand Dictionnaire Terminologique

  3. #123
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 418
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 418
    Points : 5 816
    Points
    5 816
    Par défaut
    salut ,

    je doit pas être a jour au niveau des code ou alors on parle pas de la même chose
    pour @winamax ... les if then else imbriqué ne sont pas plus simple à lire que mon expression suivi de son commentaire ...
    mais comme je l'avais dis c'est plus une question d’esthétisme que de performance dans ce cas
    je pense comme toi que cela fait exactement la même chose.

    je n'ai pas lu ton code c’était celui de @jipété que je rectifiais.

    @jipete le ce trouvais au niveau des courbes et pas du dégradé dans la boucle mais peut être l'a tu rectifié par toi même
    j'ai réécrit le code dans "lazarus" pour pouvoir comprendre ce que vous vouliez faire
    c'est pour cela que par exemple le CalcMat_img001 je l'ai renommé CalcMat_degrade et l'autre en CalcMat_Courbe afin de bien distingué les deux éléments.

    peut être faut il que je récupère des sources à jour pour être sûre que l'on parle de la même chose
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  4. #124
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 720
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 720
    Points : 15 106
    Points
    15 106
    Par défaut
    Citation Envoyé par anapurna Voir le message
    peut-être faut-il que je récupère des sources à jour pour être sûr que l'on parle de la même chose
    Yakà demander
    Mais attention :
    - mes procédures de dessins n'ont pas été renommées avec tes noms (qui sont sympathiques, au demeurant :cool: ) ;
    - j'ai conservé plein de commentaires, certains sont intéressants à lire ;
    - j'ai renommé coef_C en iCoef_C pour bien me souvenir que la fonction est inline, histoire de speeder un peu plus.

    Code pascal : 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
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    //////////////////////////////////////////////////////////////////////
    ////////////////////////////////// WIWAXIA ///////////////////////////
    //////////////////////////////////////////////////////////////////////
    // Fonction Coefficient couleur dépendant du paramètre G.
    // Il s'agit en fait d'un facteur de correction non linéaire Fcnl(g, w).
    FUNCTION CcG(G1, W1: Real): Real; inline;
    VAR p, q: Real;
    BEGIN
      p:= (G1 - 1) * W1;
      q:= 1 + p;
      p:= G1 * W1;
      CcG:= p / q
    END;
     
    FUNCTION iCoef_C(Pil: byte; t: Real): real; inline;
    VAR u, w, g: Real;
    BEGIN
      g := 40;//2.5;//40;//0.0256;// , 0.064 , 0.16 , 0.4 , 2.5 , 6 , 16 , 40  -- g à 0 = image noire
    {  IF t>1 THEN u:= t - 2              // décalage d'une période vers la gauche
             ELSE IF t<-1 THEN u:= t + 2 // décalage d'une période vers la droite
                          ELSE u:= t;
      //     v:= Abs(u); w:= (3 * v) - 2; // old v1
      //w := 2 - (3 * Abs(u));
        w := (3 * Abs(u)) - 1;
    //  w := (3 * Abs(t)) - 1; // posts 15/11
      IF w>1 THEN w:= 1 ELSE IF w<0 THEN w:= 0;
      CASE Pil OF
        0: iCoef_C:= w;           // si w     = 0.2   | 0.5  | 0.8
        1: iCoef_C:= Sqr(w);      // sqr      = 0.04  | 0.25 | 0.64
        2: iCoef_C:= Sqr(Sqr(w)); // sqr(sqr) = 0.001 | 0.06 | 0.41
        3: begin u:= Sqrt(1 -w); iCoef_C:= Sqr(1 - u); end;
        4: iCoef_C:= Sqrt(w);     // sqrt     = 0.4   | 0.7  | 0.9
        5: begin u:= Sqr(1 - w); iCoef_C:= Sqrt(1 - u); end;
        //9: iCoef_C:= g*w/(1 + (g-1)*w);
        9: iCoef_C:= CcG(g, w);
        ELSE iCoef_C:= Sqrt(w);
      END;  }
      IF Odd(Pil) THEN w:= (1/2) + cos(Pi * t)
                  ELSE w:= (1/2) - cos(Pi * t);
      IF w>1 THEN w:= 1
             ELSE IF w<0 THEN w:= 0;
      iCoef_C:= CcG(g, w)
    END;
     
    procedure wiwaxia(Pilote: byte; dst: TBitmap);
    CONST
      Lim = 5000.0; // finesse du dessin des graphiques : 500 = grossier, 5000 = origine, 50000 = peut-être trop
      Rapport = 2 / 3;
      offset = 20;
      MaxByte = 255;
      Cro: Pixel = (MaxByte, 0, 0);
      Cve: Pixel = (0, MaxByte, 0);
      Cbl: Pixel = (0, 0, MaxByte);
      Dim_Max = 1600;
     
    TYPE
      Pixel = ARRAY[1..3] OF Byte;
      Tab_Pix = ARRAY[0..Dim_Max, 0..(Dim_Max div 2)] OF Pixel;
      //Tab_Pix = ARRAY OF ARRAY OF Pixel;  // double le temps d'exécution...
     
    VAR
      h,w : integer;
      Haut_Image, Larg_Image, LargeurMoinsUn: LongInt;
      ZoneAffGraphik, DemiHauteur: LongInt;
      Matrix: Tab_Pix;
      PixelNoir: Pixel;
      Px: Pixel;
      r: Real;
      {$IFDEF WINDOWS}
      ss,dd   :  pRGBTriple; // assumes pf24bit scanlines
      {$ELSE}
      ss,dd   :  pRGBQuad;   // assumes pf24bit scanlines
      {$ENDIF}
     
      PROCEDURE CalcMat_Im02(Hauteur: LongInt; VAR Matrix: Tab_Pix); // dégradé
      VAR
        x, y: LongInt;
      BEGIN
        FOR x:= 0 TO LargeurMoinsUn DO begin
          r:= ((2 * x)/LargeurMoinsUn)-1;// enlever le -1 décale vers la gauche de 1/2 largeur
          Px[1]:= Round(MaxByte * iCoef_C(Pilote, r));
          Px[2]:= Round(MaxByte * iCoef_C(Pilote, r - Rapport));
          Px[3]:= Round(MaxByte * iCoef_C(Pilote, r + Rapport));
          FOR y := (Hauteur div 2) TO Hauteur DO Matrix[x, Hauteur-y]:= Px;//de (Haut div 2) à 0
        end;     // Hauteur div 2 ET PAS DemiHauteur (trop grand)
      END;
     
      PROCEDURE CalcMat_Im01(Hauteur: LongInt; VAR Matrix: Tab_Pix); // graphique
      VAR
        x, y, k: LongInt;
        fLarg_Image, fLargeurMoinsUn, Real_Inc, R0: float; // souvi
      BEGIN
        ZoneAffGraphik:= Hauteur - offset;
        fLarg_Image := Larg_Image;
        fLargeurMoinsUn := LargeurMoinsUn * 0.5;
        Real_Inc := fLarg_Image / (2.0 * Lim) ;
    //    R0 := (-Lim -1) * Real_Inc ;
        R0 := -Real_Inc ;
    //mainform.memo1.Lines.Add(inttostr(round((2*Lim)-1)) +' '+inttostr(x) +' '+floattostr(R0)); exit;
        FOR k:= round(-Lim) TO round(Lim-1) DO BEGIN  // Lim = 5000
    //    FOR k:= 0 TO round(2*Lim-1) DO BEGIN  // Lim = 5000
          r:= k / Lim;
    //      //x:= Round(((r+1) * (Larg_Image-1)) / 2); // Inc(x); // position horizontale, si présent, 1re colonne moisie
    //      x:= Round(((r+1) * LargeurMoinsUn) / 2); // Inc(x); // position horizontale, si présent, 1re colonne moisie
          R0 := R0 + Real_Inc;
          x := round(R0 + 0.5);
    //      x:= round((r+1) * fLargeurMoinsUn); // essai moi -- Inc(x); // position horizontale, si présent, 1re colonne moisie
    //mainform.memo1.Lines.Add(inttostr(k) +' '+inttostr(x) +' '+floattostr(R0));
          // avec LargeurMoinsUn ne dépasse pas 1535
    //mainform.memo1.Lines.Add(inttostr(x) +' '+floattostr(((r+1) * (Larg_Image-1)) / 2));
    // 2 lignes essai tbc92
    //    For x := 0 to Larg_Image-1 do begin             // Ainsi x varie de 0 à 1535 ... c'est à dire pointe directement sur l'indice de la colonne qu'on va traiter .
    //      r := (x/(LargeurMoinsUn) *2)-1;         // Ainsi r varie entre -1 et 1 comme dans ta version , donc en principe rien à changer dans le reste du code.
          y:= Round(DemiHauteur * iCoef_C(Pilote, r));
            Matrix[x, ZoneAffGraphik - y]:= Cro;
          y:= Round(DemiHauteur * iCoef_C(Pilote, r - Rapport));
            Matrix[x, ZoneAffGraphik - y]:= Cve;
          y:= Round(DemiHauteur * iCoef_C(Pilote, r + Rapport));
            Matrix[x, ZoneAffGraphik - y]:= Cbl;
        END
      END;
     
    begin
      Larg_Image := dst.Width;
      Haut_Image := dst.Height;
      DemiHauteur:= Haut_Image div 2;
      LargeurMoinsUn := Larg_Image-1; // pour Im02
    //  SetLength(Matrix, Larg_Image+1, Haut_Image); //+1 car x du graphique arrive à 1536... -- corrigé 14/11/2016
      //PixelNoir[1]:=0;  PixelNoir[2]:=0;  PixelNoir[3]:=0;  // noir
      PixelNoir[1]:=128;  PixelNoir[2]:=128;  PixelNoir[3]:=128;  // gris
      for w := 0 to Larg_Image-1 do for h := 0 to Haut_Image-1 do Matrix[w,h] := PixelNoir;
     
      CalcMAt_Im01(Haut_Image, Matrix);  // graphique
      CalcMAt_Im02(Haut_Image-(offset * 4), Matrix); // dégradé
      with dst do begin
        BeginUpdate();
        for h := 0 to (Height - 1) do begin
        {$IFDEF WINDOWS}
          dd := pRGBTriple(RawImage.GetLineStart(h));
          for w := 0 to (Width - 1) do
            dd[w] := iRGBtoRGBTriple(Matrix[w,h][1], Matrix[w,h][2], Matrix[w,h][3]);
        {$ELSE}         //     positions     R               G               B
          dd := pRGBQuad(RawImage.GetLineStart(h));
          for w := 0 to (Width - 1) do
            dd[w] := iRGBAtoRGBAQuad(Matrix[w,h][1], Matrix[w,h][2], Matrix[w,h][3], 255);// 255 = pas de transparence
       {$ENDIF}
        end;
        EndUpdate();
      end;
    end;

    Et la manière de l'appeler, depuis l'ihm, avec un bouton, un memo et une image 768 x 512 :
    Code pascal : 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
    procedure TMainForm.Button7Click(Sender: TObject); // 25 millisec -> 45 ce soir !?
    const                                              // selon type d'array (stat. ou dyn.)
      Pilote = 2;
    var
      StartTime, StopTime, Delta    :  QWord;
      dst: TBitmap;
    begin
      {$IFDEF LINUX}
      StartTime := GetTickCount64;
      {$ENDIF}
      image5.Height:=512; image5.Top:=360;
      image5.Stretch:=True;
      dst := TBitmap.Create;
      dst.PixelFormat := pf24bit;
      dst.SetSize(1536, 512);
     
      memo1.Clear; memo1.Lines.Add('Pilote : ' + InttoStr(Pilote));
      wiwaxia(Pilote, dst);          // 20 millisec dégr+graph
      image5.Picture.Assign(dst);
     
      dst.Free;
     
      {$IFDEF LINUX}
      StopTime := GetTickCount64;
      Delta := StopTime - StartTime;
      //Caption := IntToStr(Delta) + ' nanosecondes';
      Caption := FloatToStr(Delta * ONE_OVER_MILLIER) + ' microsecondes';
      //Caption := FloatToStr(Delta * ONE_OVER_MILLION) + ' millisecondes';
      {$ENDIF}
    end;
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  5. #125
    Membre émérite

    Homme Profil pro
    Formation: Chimie et Physique (structure de la matière)
    Inscrit en
    Décembre 2010
    Messages
    1 333
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 77
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Formation: Chimie et Physique (structure de la matière)
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 333
    Points : 2 570
    Points
    2 570
    Billets dans le blog
    9
    Par défaut
    Salut,

    Citation Envoyé par Jipété Voir le message
    ... Pour répondre à wiwaxia, ça doit être des bidouilles à moi, ça. ...
    Nul n'est tenu à une séance d'expiation publique; nous ne sommes pas en Corée du Nord, et chacun d'entre nous avait des détails à rectifier.
    Comme je viens de le rajouter au post précédent, il vaut mieux s'en tenir à la dernière version proposée (1) ... ou alors présenter clairement le programme en cause.

    Citation Envoyé par Jipété Voir le message
    ... Sinon je te rassure, je suis un grand amateur de ce genre d'optimisation, je me suis même inventé, pour ce programme, une variable nommée LargeurMoinsUn, si si !, qui me permet de faire des boucles genre for i := 0 to LargeurMoinsUn do..., et oui !
    Je ne suis pas inquiet, et j'ai moi-même prosaïquement introduit la variable locale
    Encore plus court.

    Bonne journée.

    (1): d'autant plus qu'il devient difficile de suivre toutes les réponses successives ...


    Le français, notre affaire à tous
    Grand Dictionnaire Terminologique

  6. #126
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 629
    Points : 10 554
    Points
    10 554
    Par défaut
    Citation Envoyé par wiwaxia Voir le message
    # Tu propose ensuite ensuite une procédure corrective CLAMP_0_1(VALUE) qui remplace deux instructions conditionnelles: où est l'avantage ? En quoi est-ce plus bref ?
    1. Je ne t'en veux pas lorsqu'on voit la tronche de ton code jonché de CalcMat_Im, Creation_F, AffT_ImFi, Calc_Cf_2
    2. Si on parle bien de code plus concis. Parce qu'on va remplacer 2 tests (5-6 lignes) par une macro/ un appel d'une fonction inline (est-ce en Delphi il a ce genre de chose?)


    Le but c'est la lisibilité du code. exemple: output_buffer = CLAMP_0_1( /*gros calcul*/);.

  7. #127
    Membre émérite

    Homme Profil pro
    Formation: Chimie et Physique (structure de la matière)
    Inscrit en
    Décembre 2010
    Messages
    1 333
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 77
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Formation: Chimie et Physique (structure de la matière)
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 333
    Points : 2 570
    Points
    2 570
    Billets dans le blog
    9
    Par défaut Trop de concision nuit à la rapidité.
    @ anapurna: Bonjour,

    Je reviens sur l"une de tes remarques de cette nuit:

    Citation Envoyé par anapurna Voir le message
    ... autre petit truc là c'est plus esthétique voir pour la compréhension
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
      IF w>1 THEN w:= 1
          ELSE IF w<0 THEN w:= 0;
    à remplacer par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     w := max(min(w,1),0);// on borne w entre o et 1
    ... / ...
    voila quelques améliorations à faire
    qui m'a paru intéressante, bien qu"elle m'ait inspiré de la méfiance:

    Sans doute (je suis maintenant trop fatigué pour vérifier) ... si l'on est familier de ce genre de choses; j'ai déjà dit ce que je pensais des fonctions emboîtées: ce que tu souhaites remplacer a le mérite d'être clair et facilement vérifiable, et ta formule doit de toutes façons effectuer les mêmes opérations - un programme source est fait pour être (re)lu, et l'instruction la plus concise n'est pas forcément souhaitable.
    Un membre du club (picodev) avait fait, il y a quelques mois et au cours d'un autre débat, une intervention tout à fait pertinente au sujet de la recherche de la concision optimale, au niveau du code, et des contre-performances qu'elle pouvait entraîner. Je n'ai malheureusement pas pu retrouver ce texte.

    Cependant, j'ai programmé par curiosité l'exécution chronométrée des deux procédures mises en comparaison:
    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
     
     
     CONST Imax = 700000000; Kmax = 3 * Imax;   
     
     PROCEDURE AffT;
       BEGIN
         E(0010); Wt(5, 15, 'Temps de calcul: DeltaT = ');
         E(0012); Write(DeltaT_Chrono:5:2, '  s'); A_
       END;
     
     PROCEDURE P2;                      // Imax = 7E8   T = 90.43 s 90.51 s
       VAR i, j: Z_32; r, s: Reel;
       BEGIN
         Top0_Chrono;
         FOR i:= 1 TO Kmax DO BEGIN
                                r:= (i / Imax);
                                s:= Max2Re(Min2Re(r, 2), 1)
                              END;
         Top1_Chrono
       END;
                                        // Imax = 7E8   T = 25.68 s 25.74
     PROCEDURE P1;
       VAR i, j: Z_32; r, s: Reel;
       BEGIN
         Top0_Chrono;
         FOR i:= 1 TO Kmax DO BEGIN
                                r:= (i / Imax);
                                IF (r>2) THEN s:= 2
                                         ELSE IF (r<1) THEN s:= 1
                                                       ELSE s:= r
                              END;
         Top1_Chrono;
       END;
     
     BEGIN
       P1;   // ou P2
       AffT
     END.
    Je te laisse le soin de traduire.
    J'ai obtenu pour le même nombre d'itérations (21E8) un délai d'exécution T1 = 25.7 s dans le premier cas,
    et un délai T2 = 90.5 s - soit ~ 3.5 fois plus grand - dans le cas des 2 fonctions imbriquées (Min(x, y) et Max(x, y)).
    Comme quoi la concision n'implique pas la rapidité ... l'emboîtement des fonctions prédéfinies bride le logiciel !
    Un peu comme si l'on se servait d'une Jaguar comme une brouette.

    PS: Il va sans dire (mais beaucoup mieux en le disant) que la fonction définie sur [0 ; 3] et calculée dans tous les cas, est donnée par les relations:
    y = 1 (pour x <= 1) ; y = x (pour 1 < x < 2) ; y = 2 (pour 2 < x) .
    Dans la boucle (x) varie de (1/Imax ~ 0) à (3).


    Le français, notre affaire à tous
    Grand Dictionnaire Terminologique

  8. #128
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 418
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 418
    Points : 5 816
    Points
    5 816
    Par défaut
    salut

    a bien y réfléchir tout ceci me parait normal
    le fait de faire systématique un min et un max alors que toi tu fait au max 2 test au min 1
    ce qui pourrait expliquer cela
    bon j'en conviens je me suis un peut emballé sur l'esthétisme au détriment de l'efficacité

    je vais créer ma propre fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    Function borneMinMax(aValue,aMax,aMin : double) : double
    begin
      if aValue<aMin Then
         Result :=aMin
      else 
       if aValue > aMax Then 
         Result :=aMax
      else 
         Result := aValue;
    end;
    PS : c'est un joke les test vont bien aussi
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  9. #129
    Membre émérite

    Homme Profil pro
    Formation: Chimie et Physique (structure de la matière)
    Inscrit en
    Décembre 2010
    Messages
    1 333
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 77
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Formation: Chimie et Physique (structure de la matière)
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 333
    Points : 2 570
    Points
    2 570
    Billets dans le blog
    9
    Par défaut Trop de concision nuit à la rapidité (suite)
    Bonjour,

    @ anapurna: J'ai poursuivi l'examen de cette question.

    Avec l'expression Min(Max(r, 1), 2) , symétrique de la précédente, les temps obtenus sont du même ordre: 91.5 s , toujours très supérieurs à celui de l'algorithme le plus direct (25.7 s).
    Autre variante: les instructions conditionnelles étant rassemblées dans une fonction Bornage(a, b, x),
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
     FUNCTION Bornage(a, b, x: Reel): Reel;
       VAR y: Reel;
       BEGIN
         IF x>2 THEN y:= 2
                ELSE IF x<1 THEN y:= 1
                            ELSE y:= x;
         Bornage:= y
       END;
    les délais sont alors de 52.7 s , que cette fonction figure dans le même programme ou soit reportée dans l'unité. La "proximité" du codage et le nombre d'appels de ces fonctions joue apparemment un rôle déterminant.

    Je ne connaissais pas ces combinaisons algorithmiques. Ce sont des curiosités logiques intéressantes, mais qui n'améliorent apparemment pas l'exécution des programmes.

    Il est vrai que la boucle choisie était particulièrement longue: N = 2.1E9 (il est difficile de faire mieux: MaxLongInt = 231 - 1 ~ 2.147E9); mais dans le cas d'une image, le nombre d'indices de couleur peut atteindre des valeurs assez élevées (3*Npixel = 3*20002 = 12E6 pour une image 2000x2000).

    D'autres membres du forum pourraient apporter des informations intéressantes sur ce sujet. Il conviendrait peut-être de le porter en discussion.


    Le français, notre affaire à tous
    Grand Dictionnaire Terminologique

  10. #130
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 720
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 720
    Points : 15 106
    Points
    15 106
    Par défaut
    Et bonjour !

    On va dévier un peu des dégradés mais c'est pas grave ; je reviens sur ce point :
    Citation Envoyé par wiwaxia Voir le message
    que cette fonction figure dans le même programme ou soit reportée dans l'unité. La "proximité" du codage et le nombre d'appels de ces fonctions joue apparemment un rôle déterminant.
    Je me suis rendu compte que des petites fonctions appelées un nombre démentiel de fois (genre trafiquer la couleur de tous les pixels d'une grosse image) avaient tout intérêt à être déclarées "inline" (en Delphi/Lazarus tu termines la ligne de la déclaration par inline; sans oublier de l'activer dans le projet avec {$inline on} ; tu adapteras à ton outil) car tout appel de fonction nécessite de sauvegarder le contexte d'exécution du programme avant l'appel pour le restaurer après, toutes choses non nécessaires avec l'inlinisation : ça fait gagner un temps fou.

    Autre chose de rigolo : dans une boucle (surtout celles qui bricolent avec l'ihm, genre mise à jour de compteurs, de barre de progression, etc.), il est nécessaire de laisser "respirer" le programme et la machine, sinon on a l'impression que l'ihm est figée (et le fameux message de Windows depuis Vista ou 7, "Ce programme ne répond pas..."). Solution en Pascal avec Application.ProcessMessages; dans le corps de la boucle, tout le monde connait ça, en VB c'est DoEvents et pour les autres langages vous regardez votre doc.
    Sauf que c'est coûteux.
    Alors il est conseillé de n'appeler cette "pompe à messages" que de temps en temps, genre
    Code pascal : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for i := 0 to BorneLongue do begin
      if (i mod 20 = 0) then Application.ProcessMessages;
      suite_boucle;
    end;
    et c'est là qu'on rigole : je me suis rendu compte que cet ensemble division puis extraction du reste et test était très coûteux, en tout cas la boucle met plus de temps à s'exécuter quand le test est présent que quand il est absent !
    Je vous laisse méditer là-dessus et faire vos propres tests.
    Code pascal : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    for i := 0 to BorneLongue do begin
      if (i mod 20 = 0) then // plus rapide quand test commenté !
        Application.ProcessMessages;
      suite_boucle;
    end;
    Bonne journée,
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  11. #131
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 418
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 418
    Points : 5 816
    Points
    5 816
    Par défaut
    salut

    je suis un peut surpris je pensais betement que pascal optimisé et que l'apelle de fonction ne prenais pas tans de temps que ça
    effectivement c'est a voir

    peut etre qu'en utilisant le mot reservé inline ceci arrangera le temps de traitement
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  12. #132
    Membre émérite

    Homme Profil pro
    Formation: Chimie et Physique (structure de la matière)
    Inscrit en
    Décembre 2010
    Messages
    1 333
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 77
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Formation: Chimie et Physique (structure de la matière)
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 333
    Points : 2 570
    Points
    2 570
    Billets dans le blog
    9
    Par défaut
    Pour la commande inline, je vais consulter la documentation.
    Il faut vraiment que je reprenne le Free Pascal ! Tous les échanges de ce forum m'ont d'ailleurs donné envie de m'y remettre.

    Autre chose de rigolo : dans une boucle ... , il est nécessaire de laisser "respirer" le programme et la machine,
    J'ai déjà eu l'occasion de faire ce constat: on ne se rend compte du coût réel d'une instruction que sur une très longue boucle.
    Et lorsque l'exécution se prolonge sur plusieurs minutes (parfois 10 ou 20), je m'assure de la bonne marche par l'affichage du compteur (i) - cela permet de prendre patience - par une instruction sélective du type:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
       if (i mod 1000 = 0) then Affichage(i);
    Je te propose justement une petite variante, au sujet du bloc d'instructions que tu donnes en exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for i := 0 to BorneLongue do begin
      if (i mod 20 = 0) then Application.ProcessMessages;
      suite_boucle;
    end;
    en programmant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    var j: Byte;
    for i := 0 to BorneLongue do begin
      j:= i mod 20;
      if  (j= 0) then Application.ProcessMessages;
      suite_boucle;
    end;
    Je serais curieux de savoir ce que devient le temps d'exécution ...


    Le français, notre affaire à tous
    Grand Dictionnaire Terminologique

  13. #133
    Rédacteur/Modérateur

    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Décembre 2013
    Messages
    4 053
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes
    Secteur : Conseil

    Informations forums :
    Inscription : Décembre 2013
    Messages : 4 053
    Points : 9 393
    Points
    9 393
    Par défaut
    Pour éviter la division par 20, on peut remplacer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    for i := 0 to BorneLongue do begin
      if (i mod 20 = 0) then Application.ProcessMessages;
      suite_boucle;
    end;
    par :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    i_pause = 20 
    for i := 0 to BorneLongue do begin
      if (i = i_pause ) then 
        i_pause +=20
        Application.ProcessMessages;
      end if ;
      suite_boucle;
    end;
    N'oubliez pas le bouton Résolu si vous avez obtenu une réponse à votre question.

  14. #134
    Membre émérite

    Homme Profil pro
    Formation: Chimie et Physique (structure de la matière)
    Inscrit en
    Décembre 2010
    Messages
    1 333
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 77
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Formation: Chimie et Physique (structure de la matière)
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 333
    Points : 2 570
    Points
    2 570
    Billets dans le blog
    9
    Par défaut
    Très bonne astuce. J'en prends note.


    Le français, notre affaire à tous
    Grand Dictionnaire Terminologique

  15. #135
    Membre émérite

    Homme Profil pro
    Formation: Chimie et Physique (structure de la matière)
    Inscrit en
    Décembre 2010
    Messages
    1 333
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 77
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Formation: Chimie et Physique (structure de la matière)
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 333
    Points : 2 570
    Points
    2 570
    Billets dans le blog
    9
    Par défaut
    J'ai repris le programme de chronométrage dans le cas de 2 sortes de blocs d'instructions.

    1°) L'affichage sélectif d'un compteur, en comparant 3 procédures (P1, P2, P3):
    Code pascal : 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
    41
    42
    43
     
                                  // Imax = 200E6
     PROCEDURE P3;                // 15.43 s 15.32 s 15.29 s m = 15.35
       VAR i, j: Z_32;            // 15.25 s 15.32 s 15.32 s m = 13.30
       BEGIN
         Top0_Chrono; j:= Jm;
         FOR i:= 1 TO Imax DO (*BEGIN      *)
                                IF (i=j) THEN BEGIN
                                                 Inc(j, Jm);
                                                 GotoXY(2, 5);
                                                 Write(i:10)
                                               END
                         (*     END*);
         Top1_Chrono;
       END;
     
     PROCEDURE P2;                // 25.01 s 24.07 s 24.34 s m = 24.47
       VAR i, j: Z_32;
       BEGIN
         Top0_Chrono;
         FOR i:= 1 TO Imax DO BEGIN
                                j:= (i MOD Jm);
                                IF (j=0) THEN BEGIN
                                                GotoXY(2, 5);
                                                Write(i:10)
                                              END
                              END;
         Top1_Chrono;
       END;
     
     
     PROCEDURE P1;                // 26.32 s 24.16 s 24.33 s m = 24.94
       VAR i: Z_32;
       BEGIN
         Top0_Chrono;
         FOR i:= 1 TO Imax DO BEGIN
                                IF ((i MOD Jm)=0) THEN BEGIN
                                                         GotoXY(2, 5);
                                                         Write(i:10)
                                                       END
                              END;
         Top1_Chrono;
       END;
    faisant respectivement intervenir:
    a) l'expression directe de la condition: IF ((i MOD Jm)=0) THEN
    b) une variable intermédiaire: j:= (i MOD Jm); IF (j=0) THEN ...
    c) la variante proposée par tbc92:
    d) une version un peu plus brève, résultant de la suppression d'un couple de délimiteurs (begin ... end) devenus inutiles.

    Résultats obtenus pour Imax = 200E6 itérations: Ta = 24.9 s ; Tb = 24.5 s ; Tc = 15.35 s ; Td = 15.30 s .
    Remarquer:
    # la légère diminution du temps d'exécution (1 à 2 %) résultant de l"insertion d'un intermédiaire de calcul;
    # la réduction significative (38 %) accompagnant le remplacement de la division par une addition; la recommandation de tbc92 est à retenir.

    2°) L'expression particulièrement chargée d'un entier X := round(C*(1-Abs((round(H) div 60) mod 2)-1)), figurant dans un programme de Jipété posté le 24/10/2016(17h58), et dont le déchiffrement n'avait rien d'évident (je n'ai d'ailleurs pas tout compris, mais ici cela n'a pas d'importance).
    Trois procédures (P4, P5 et P6) ont ici été comparées:
    a) la formule initiale, utilisant le réel (h);
    b) un algorithme détaillé, utilisant 5 termes intermédiaires (H1, H2, H3, H4, r);
    c) un troisième plus condensé, n'en faisant intervenir que deux (H2, H4).
    Code pascal : 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
    41
    42
     
     PROCEDURE P6;                                    // 32.32 s 32.10 s
       CONST Cx = 360 / Imax; C = 200.0;
       VAR H2, H4, i, x: Z_32; h: Reel;
       BEGIN
         Top0_Chrono;
         FOR i:= 0 TO Imax DO BEGIN
                                h:= Cx * i;
                                H2:= Round(h) DIV 60;
                                H4:= Abs((H2 MOD 2) - 1);
                                x:= Round((C * (1 - H4)) - 1)
         //   x:= Round(C*(1 - Abs((Round(h) DIV 60) MOD 2) - 1))
                              END;
         Top1_Chrono;
       END;
     
     PROCEDURE P5;                          // 76.43 s (20E8) 38.25 s (10E8)
       CONST Cx = 360 / Imax; C = 200.0;                   // 38.55 s
       VAR H1, H2, H3, H4, i, x: Z_32; h, r: Reel;
       BEGIN
         Top0_Chrono;
         FOR i:= 0 TO Imax DO BEGIN
                                h:= Cx * i;        H1:= Round(h);
                                H2:= H1 DIV 60;    H3:= H2 MOD 2;
                                H4:= Abs(H3 - 1);  r:= C * (1 - H4);
                                x:= Round(r - 1)
         //   x:= Round(C*(1 - Abs((Round(h) DIV 60) MOD 2) - 1))
                              END;
         Top1_Chrono;
       END;
     
     PROCEDURE P4;                          // 61.95 s (20E8)  31.27 s (10E8)
       CONST Cx = 360 / Imax; C = 200;                     //  31.28 s
       VAR i, x: Z_32; h: Reel;
       BEGIN
         Top0_Chrono;
         FOR i:= 0 TO Imax DO BEGIN
                                h:= Cx * i;
                                x:= Round(C*(1 - Abs((Round(h) DIV 60) MOD 2) - 1))
                              END;
         Top1_Chrono;
       END;
    Résultats pour 109 itérations: Ta = 31.1 s ; Tb = 38.3 s ; Tc = 33.2 s .

    Le temps de calcul augmente avec le nombre de variables intermédiaires, mais d'une manière modérée (15 et 7 %).
    Une décomposition de la formule en un petit nombre d'étapes reste avantageuse par la clarté qu'elle apporte, et a fortiori sur des durées plus brèves ne dépassant pas la seconde.


    Le français, notre affaire à tous
    Grand Dictionnaire Terminologique

  16. #136
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par wiwaxia Voir le message
    # la réduction significative (38 %) accompagnant le remplacement de la division par une addition; la recommandation de tbc92 est à retenir.
    Je ne dirais pas "je l'avais bien dit"


    (c'est généralement fait par un développement en suite de Taylor dans un processeur....)
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  17. #137
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 720
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 720
    Points : 15 106
    Points
    15 106
    Par défaut
    Citation Envoyé par wiwaxia Voir le message
    # la réduction significative (38 %) accompagnant le remplacement de la division par une addition; la recommandation de tbc92 est à retenir.
    Alors ça doit dépendre de tout ce qu'il y a autour (calculs, tests, etc.) parce qu'avec une simple boucle et rien d'autre, ça se vaut :

    Code pascal : 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
    /////////// test rapide ////////////////////
    const
      BorneLongue = 1000000;
     
    procedure TForm1.Button5Click(Sender: TObject); // 210 millisec + ou - 10
    var
      Start :  DWORD;
      i: integer;
    begin
      Start := GetTickCount;
      for i := 0 to BorneLongue do begin
        if (i mod 20 = 0) then
          Application.ProcessMessages;
      end;
      form1.Caption := IntToStr(GetTickCount-Start) + ' millisec';
    end;
     
    procedure TForm1.Button6Click(Sender: TObject); // 210 millisec + ou - 10
    var
      Start :  DWORD;
      i,i_pause: integer;
    begin
      i_pause := 20;
      Start := GetTickCount;
      for i := 0 to BorneLongue do begin
        if (i = i_pause ) then begin
          i_pause +=20;
          Application.ProcessMessages;
        end;
      end;
      form1.Caption := IntToStr(GetTickCount-Start) + ' millisec';
    end;

    Et par rapport à ce que je disais ce matin, bien sûr je ne retrouve pas le cas de figure et c'est bien dommage, car ce soir avec ma simple boucle ça ne fonctionne plus : si je commente le test if (i mod 20 = 0) then la boucle devient 10 fois plus longue.
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  18. #138
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Jipété Voir le message
    ...
    Je pense surtout que tu devrais utiliser un vrai outil de profiling

    Chronométrer le temps est très aléatoire, il y a au moins 3 temps : le temps réel, le temps utilisateur, le temps process...

    Suivant la charge, le scheduling, etc, tout peut varier...

    Sous Windows, toutes les icônes sur le bureau sont des running process par exemple (si tu regardes les "tâches" tu verras qu'ils tournent...)... Sous unixoides, tu as la capacité de seulement sélectionner le temps process..

    Les outils de profiling sont normalement faits pour ça, et pour donner les % relatifs d'utilisation...

    Quant aux mesures absolues, j'avais mis à disposition dans la section C de code-source un chronomètre en absolu... je vais re-chercher la référence et j'éditerais ce post...

    [EDIT]

    OK c'est ici

    [/EDIT]
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  19. #139
    Rédacteur/Modérateur

    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Décembre 2013
    Messages
    4 053
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes
    Secteur : Conseil

    Informations forums :
    Inscription : Décembre 2013
    Messages : 4 053
    Points : 9 393
    Points
    9 393
    Par défaut
    L'instruction la plus longue de ton process , c'est l'instruction Application.ProcessMessages;
    Ca, c'est acquis. C'est un peu paradoxal, on met cette instruction pour rassurer l'utilisateur quand le programme est long , et pour rassurer l'utilisateur, on rallonge délibérément le temps de traitement de façon importante.

    Cette instruction, soit on l'exécute BorneLongue fois, soit on l'exécute moins souvent : 20 fois moins souvent dans le scénario étudié.

    Le test que tu as fait de de comparer 2 scénarios, l'un où on exécute cette instruction coûteuse BorneLongue/20 fois, et l'autre où on l'exécute BorneLongue fois ( quand tu mets la ligne if imod10 0 en commentaire, c'est ce qui se produit).
    Bien évidemment, si on exécute cette instruction couteuse 20 fois plus souvent, le traitement est plus lent.

    La comparaison utile c'est : on veut réactualiser l'affichage de temps en temps, mais pas trop souvent. Le seuil choisi est de rafraîchir l' affichage BorneLongue/20 fois.
    Pour cela on a 2 options, c'est tester si mod(i,20) = 0, ou bien de tester si i = i_pause, en incrémentant i_pause comme il faut.
    Et le résultat de Wiwaxia est : l'option 2 est 38% plus rapide que l'option 1.

    Ce résultat est très encourageant mais n'est pas réellement significatif. Quand on a une boucle qui ne fait pas grand chose, voire rien, ajouter une division est effectivement un surcoût important. Mais quand dans le corps de la boucle, il y a des traitements un peu plus réalistes (calcul de la couleur d'un point dans un dégradé par exemple), alors l'ajout ou la suppression d'une division (via le test mod(i,20)=0 ) est quasiment marginal.
    N'oubliez pas le bouton Résolu si vous avez obtenu une réponse à votre question.

  20. #140
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 720
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 720
    Points : 15 106
    Points
    15 106
    Par défaut
    Citation Envoyé par souviron34 Voir le message
    Je pense surtout que tu devrais utiliser un vrai outil de profiling
    [EDIT]

    OK c'est ici

    [/EDIT]
    Vu, merci, mais j'ai le même sous Linux en Pascal, y a des gens qui ont porté ça, j'ai reconnu le nom des structures utilisées.
    Je n'ai pas voulu l'utiliser ici en me disant que si quelqu'un voulait tester rapidement et sous Windows, il n'avait qu'à faire un copier-coller sans se prendre la tête et être obligé de jongler avec des DEFINE, le but de la manip étant de comparer des choses différentes sur la même machine et pas des choses identiques sur des machines différentes.

    Citation Envoyé par tbc92 Voir le message
    Quand on a une boucle qui ne fait pas grand chose, voire rien, ajouter une division est effectivement un surcoût important. Mais quand dans le corps de la boucle, il y a des traitements un peu plus réalistes (calcul de la couleur d'un point dans un dégradé par exemple), alors l'ajout ou la suppression d'une division (via le test mod(i,20)=0 ) est quasiment marginal.
    Vu, noté, mais je m'embrouille car je gère d'autres choses en parallèle qui me mettent les neurones dans un état proche de la serpillière un lendemain de fête bien arrosée, si tu vois...

    Bon, faut que j'y retourne, en plus...
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

Discussions similaires

  1. des couleurs dans la console,comment faire?
    Par rockkornman dans le forum C
    Réponses: 3
    Dernier message: 09/05/2009, 00h01
  2. variable dans un libellé, comment faire ?
    Par chapeau_melon dans le forum WinDev
    Réponses: 2
    Dernier message: 01/02/2008, 23h08
  3. Réponses: 5
    Dernier message: 03/09/2007, 20h36
  4. Très long texte dans Quick Report - Comment faire ?
    Par delphi+ dans le forum Composants VCL
    Réponses: 2
    Dernier message: 21/08/2005, 22h18
  5. [Syntaxe] Un return dans un try... Comment faire ?
    Par chuky dans le forum Général Java
    Réponses: 13
    Dernier message: 14/01/2005, 10h33

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