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

Langage Delphi Discussion :

FillMemory avec incrément de valeur


Sujet :

Langage Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    152
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2003
    Messages : 152
    Par défaut FillMemory avec incrément de valeur
    Recherche d'une procédure efficiente (asm) basée sur la procédure FillMemory mais avec incrément de la valeur Fill.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    var
      tab : array of byte;
      Fill : byte;
     
    for i := 0 to n-1 do tab[i] := Fill +i;
    idem en version cardinal (4 bytes)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    var
      tab : array of cardinal;
      Fill : cardinal;
     
    for i := 0 to n-1 do tab[i] := Fill +i;

  2. #2
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 107
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 107
    Par défaut
    Déjà FillChar, ZeroMemory, c'est assez long, lors de l'allocation d'un grand tableau, c'est en fait ce qui prend le plus de temps.

    voir avec un QueryPerformance pour mesurer le temps à la µs sur des milliers/millions de répétitions pour comparer le code actuel avec un code différent

    Après pour commencer, l'arithmétique des pointeurs éventuellement.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    var
      tab : array of cardinal;
      Fill : cardinal;
      P: ^Cardinal;
    begin
      P := @tab[0];
      for i := 0 to n-1 do
      begin
        P^ := Fill +i;
        Inc(P); // décale de la taille selon le type de pointeur
      end;
    end;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
      for i := 0 to n-1 do
      begin
        Inc(Fill);
        P^ := Fill;
        Inc(P); // décale de la taille selon le type de pointeur
      end;
    Cela peut se joue à rien, est-il plus performant de faire un Fill + 1 à chaque tour que Fill + i
    ...

    En tout cas, ne pas utiliser i dans le for est un gain car il va remplacer "for i := 0 to n-1 do" par "for i := n-1 downto 0 do" car le test à zéro est plus rapide que le test = valeur


    FillMemory se débrouille pour remplir via un registre 6bits, sur un tableau of byte, le gain est évident, on traite 8 positions d'un coup, sur un tableau de cardinal de même dimension (soit 4 fois plus grand en mémoire), l'effet sera moindre.

    Il faut calculer la valeur Fill + 1 à Fill + n et effectuer le décalage de bits pour faire coïncider, les Byte ou Cardinal mais l'opération de décalage de bits répétés ne serait-elle pas contre performante, dans FillMemory c'est calculé au départ et réutilisé
    L'impact est mesurable, suffit de faire une FillMemory qui recalcule son bloc mémoire de remplissage à chaque fois, c'est stupide évidemment mais juste à titre démonstratif du cout de l'opération

    Comparer cela a une FillMemory qui est codé plus simplement comme ci-dessus.
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    152
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2003
    Messages : 152
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    Déjà FillChar, ZeroMemory, c'est assez long, lors de l'allocation d'un grand tableau, c'est en fait ce qui prend le plus de temps.
    J'ai comme notion que FillMemory est très rapide équivalent à ZeroMemory (pour valeur zéro).
    J'utilise pas FillChar mais probablement voisin au niveau vitesse ?

    Il y a plus rapide que FillMemory au niveau byte avec valeur fixe ?

  4. #4
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 107
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 107
    Par défaut
    FillChar est une fonction de base de Delphi, ne pas l'avoir semble difficile !
    FillMemory est une API Windows

    EDIT : Il m'a fallut pas plus de 10 minutes pour écrire ce test rapide, faut vous y mettre !

    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
    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
    151
    unit FillMemory_MainForm;
     
    interface
     
    uses
      Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
      Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
     
    type
      TForm1 = class(TForm)
        Button1: TButton;
        Memo1: TMemo;
        procedure Button1Click(Sender: TObject);
      private
        { Déclarations privées }
      public
        { Déclarations publiques }
      end;
     
    var
      Form1: TForm1;
     
    implementation
     
    {$R *.dfm}
     
    const
      FORMAT_MICRO_SECONDE = '%.2d:%.2d:%.2d:%.3d:%.3d';
     
    //------------------------------------------------------------------------------
    procedure GetBeginTime(var Value: Int64);
    begin
      QueryPerformanceCounter(Value);
    end;
     
    //------------------------------------------------------------------------------
    function ElapsedTime(const BeginTime: Int64): Int64;
    var
      EndTime, TickPerSec: Int64;
    begin
      QueryPerformanceCounter(EndTime);
      QueryPerformanceFrequency(TickPerSec);
      Result := Round((EndTime - BeginTime) / TickPerSec * 1000000);
    end;
     
    //------------------------------------------------------------------------------
    function FormatElapsedTime(ADelay: Int64; const AFormat: string = FORMAT_MICRO_SECONDE): string;
    var
      Hour, Min, Sec, MilliSecond: Int64;
    begin
      Hour := ADelay div 3600000000;
      ADelay := ADelay mod 3600000000;
      Min := ADelay div 60000000;
      ADelay := ADelay mod 60000000;
      Sec := ADelay div 1000000;
      ADelay := ADelay mod 1000000;
      MilliSecond := ADelay div 1000;
      ADelay := ADelay mod 1000;
      Result := Format(AFormat, [Hour, Min, Sec, MilliSecond, ADelay]);
    end;
     
     
    //------------------------------------------------------------------------------
    procedure TForm1.Button1Click(Sender: TObject);
    var
      qpfStart, qpfBench: Int64;
     
      i, n: cardinal;
      tab : array of cardinal;
      Fill : cardinal;
      P: ^Cardinal;
     
    begin
      n := 1000000;
      SetLength(tab, n);
     
      Fill := 10;
      GetBeginTime(qpfStart);
     
      System.FillChar(tab[0], n * SizeOf(tab[0]), 0); // Remplissage par Registre 64 Bits
     
      Memo1.Lines.Add('FillChar = '#9 + FormatElapsedTime(ElapsedTime(qpfStart)));
     
      GetBeginTime(qpfStart);
     
      Winapi.Windows.ZeroMemory(@tab[0], n * SizeOf(tab[0])); // Algo Microsoft
     
      Memo1.Lines.Add('ZeroMemory = '#9 + FormatElapsedTime(ElapsedTime(qpfStart)));
     
      GetBeginTime(qpfStart);
     
      Winapi.Windows.FillMemory(@tab[0], n * SizeOf(tab[0]), 0); // Algo Microsoft
     
      Memo1.Lines.Add('FillMemory = '#9 + FormatElapsedTime(ElapsedTime(qpfStart)));
     
     
      Fill := 10;
      GetBeginTime(qpfStart);
     
      for i := 0 to n-1 do
        tab[i] := Fill +i;
     
      Memo1.Lines.Add('for tab[i] Fill + i = '#9 + FormatElapsedTime(ElapsedTime(qpfStart)));
     
      FillChar(tab[0], n * SizeOf(tab[0]), 0);
     
      Fill := 10;
      GetBeginTime(qpfStart);
     
      for i := 0 to n-1 do
      begin
        tab[i] := Fill;
        Inc(Fill);
      end;
     
      Memo1.Lines.Add('for tab[i] Inc(Fill) = '#9 + FormatElapsedTime(ElapsedTime(qpfStart)));
     
      FillChar(tab[0], n * SizeOf(tab[0]), 0);
     
      Fill := 10;
      GetBeginTime(qpfStart);
     
      P := @tab[0];
      for i := 0 to n-1 do
      begin
        P^ := Fill + i;
        Inc(P); // décale de la taille selon le type de pointeur
      end;
     
      Memo1.Lines.Add('for P^ Fill + i = '#9 + FormatElapsedTime(ElapsedTime(qpfStart)));
     
      FillChar(tab[0], n * SizeOf(tab[0]), 0);
     
      Fill := 10;
      GetBeginTime(qpfStart);
     
      P := @tab[0];
      for i := 0 to n-1 do
      begin
        P^ := Fill;
        Inc(Fill);
        Inc(P); // décale de la taille selon le type de pointeur
      end;
     
      Memo1.Lines.Add('for P^ Inc(Fill) = '#9 + FormatElapsedTime(ElapsedTime(qpfStart)));
     
      Memo1.Lines.Add('---');
     
    end;
     
    end.
    Comment dire ce qui est plus rapide lorsque lors de 4 essais, il n'y a pas les mêmes chiffres, parce que le système peut n'importe quoi d'autres qui l'occupent et donc influe sur le résultat, il faut des milliers d'essais

    Après notez la taille du tableau 1 000 000 de Cardinal, je travaille sur de très grandes données, ceci n'est rien, juste 4 Mo


    Code resultat : 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
     
    FillChar = 	00:00:00:000:217
    ZeroMemory = 	00:00:00:000:216
    FillMemory = 	00:00:00:000:193
    for tab[i] Fill + i = 	00:00:00:003:970
    for tab[i] Inc(Fill) = 	00:00:00:003:820
    for P^ Fill + i = 	00:00:00:003:354
    for P^ Inc(Fill) = 	00:00:00:003:410
    ---
    FillChar = 	00:00:00:000:180
    ZeroMemory = 	00:00:00:000:186
    FillMemory = 	00:00:00:000:199
    for tab[i] Fill + i = 	00:00:00:003:948
    for tab[i] Inc(Fill) = 	00:00:00:003:793
    for P^ Fill + i = 	00:00:00:003:529
    for P^ Inc(Fill) = 	00:00:00:003:357
    ---
    FillChar = 	00:00:00:000:182
    ZeroMemory = 	00:00:00:000:244
    FillMemory = 	00:00:00:000:510
    for tab[i] Fill + i = 	00:00:00:003:985
    for tab[i] Inc(Fill) = 	00:00:00:003:845
    for P^ Fill + i = 	00:00:00:003:356
    for P^ Inc(Fill) = 	00:00:00:003:358
    ---
    FillChar = 	00:00:00:000:181
    ZeroMemory = 	00:00:00:000:279
    FillMemory = 	00:00:00:000:261
    for tab[i] Fill + i = 	00:00:00:003:969
    for tab[i] Inc(Fill) = 	00:00:00:003:847
    for P^ Fill + i = 	00:00:00:003:356
    for P^ Inc(Fill) = 	00:00:00:003:354
    ---

    Sur 100 répétitions

    Pièce jointe 616550Nom : Sans titre.png
Affichages : 184
Taille : 12,9 Ko
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    152
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2003
    Messages : 152
    Par défaut
    Merci, je vais tester avec un random pour la valeur Fill pour voir si cela change les résultats.

  6. #6
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 107
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 107
    Par défaut
    Avec un Random, vous changer totalement le sujet ... car vous avez une idée du coût de la fonction Random ?
    Vous partez sur un sujet cohérent de vouloir remplir un tableau avec des valeurs calculables et dépendantes de l'itération courante à une problématique aléatoire ?
    Donc profiter de Registre 64Bits pour alimenter plusieurs blocs mémoire de 8 ou 32 bits d'un seul coup, comme le fait FillChar, avec le random vous cassez cette logique

    Quel est votre besoin ?
    Car là, vous ne semblez pas maitriser votre sujet.
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

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

Discussions similaires

  1. [XL-2016] Importer des valeurs de plusieurs fichiers fermés avec incrémentation
    Par nedbrayden dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 05/06/2019, 17h57
  2. [XL-2010] Liste de valeurs avec incrément fixe
    Par MW.Tribun dans le forum Macros et VBA Excel
    Réponses: 6
    Dernier message: 23/05/2016, 17h06
  3. Réponses: 2
    Dernier message: 19/07/2015, 18h34
  4. [XL-2010] Incrémenter la valeur d'une cellule avec la roullette de la souris
    Par yamfzr dans le forum Macros et VBA Excel
    Réponses: 0
    Dernier message: 10/01/2013, 10h48
  5. Réponses: 3
    Dernier message: 10/05/2012, 20h31

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