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 :

Equivalent d'un tableau dynamique 2 dimensions ?


Sujet :

Langage Delphi

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    624
    Détails du profil
    Informations personnelles :
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 624
    Points : 199
    Points
    199
    Par défaut Equivalent d'un tableau dynamique 2 dimensions ?
    Bonjour à tous,

    J'utilise actuellement dans une de mes fonctions, plusieurs tableaux dynamiques à 1 et 2 dimensions.
    Jusqu'à présent mes volumes de données étaient assez petits donc aucun problème.

    Je dois à présent gérer des tableaux avec des valeurs d'indice beaucoup plus grandes, et donc j'ai rapidement
    des Out of Memory sur mes SetLength.

    Ma question: Par quoi remplaceriez vous les tableaux dynamiques pour d'une part faire exactement le même travail, et
    d'autre part garder mes performances (voir les améliorer si possible )

    un exemple ci-dessous de mon code pour mieux comprendre.
    Mes valeurs qui provoquent un OOM sont:

    MaxCol = 12428
    MaxRow = 6883
    FMaxCluster = 100

    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
      // Création de la matrice
      SetLength(Matrix,         MaxCol,       MaxRow);
      SetLength(Clusters,       FMaxCluster);
      SetLength(BestPartition,  MaxRow);
      SetLength(Xij,            MaxRow,       MaxCol);
      SetLength(Xi_,            MaxRow);
      SetLength(X_j,            MaxCol);
      SetLength(Cj,             MaxCol);
      SetLength(Mi,             MaxRow);
      SetLength(T,              MaxRow,       MaxCol);
      SetLength(Tj,             MaxCol);
      SetLength(Mg,             FMaxCluster);
    ==> LE OOM apparaît ici !
      SetLength(Wij,            MaxRow,       MaxCol);
    ==>
      SetLength(Bki,            FMaxCluster,  MaxCol);
      SetLength(BestCTRki,      FMaxCluster,  MaxCol);
      SetLength(BestGki,        FMaxCluster,  MaxCol);
      SetLength(BestWk,         FMaxCluster);
      SetLength(BestBk,         FMaxCluster);
      X__      := 0;
      FBestR   := 0;
      try
        for j:=0 to MaxRow-1 do
        begin
          // Indique le nombre de notices communes
          for i:=0 to MaxCol-1 do
            Matrix[i, j]  := FField.Datas[i].Records.IntersectObject(FRecords[j]);
        end;
     
        (* Calcul de Xi_ *)
        (* Xi. = p = nb de variables *)
        (* Calcul de X_j *)
        (*' X.j = nj = effectif ayant la modalité j *)
        (* '= X.. = n p *)
        For j:=0 to MaxRow-1 do
          For i:=0 to MaxCol-1 do
            IF Matrix[i, j]>0 then
            begin
              Xi_[j] := Xi_[j] + 1;
              X_j[i] := X_j[i] + 1;
              Inc(X__);
            End;
     
        (* Tableau après Transformation *)
        For j:=0 to MaxRow-1 do
          For i:=0 to MaxCol-1 do
          begin
            try
              Xij[j, i] := (Matrix[i, j]/Xi_[j])/Sqrt(X_j[i]/X__);
            except
              Xij[j, i] := 0;
            end;
            Matrix[i, j] := Xij[j, i];
          end;
    .....
    .....

  2. #2
    Membre confirmé

    Profil pro
    Inscrit en
    Mars 2002
    Messages
    1 184
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 184
    Points : 619
    Points
    619
    Par défaut
    Personnellement vu le nombre de variables indicées j'utiliserai plutôt une structure XML
    Cela permettrait une approche plus structurée.
    On dispose de fonctions de recherche assez pointues (XPath) et e n'ai jamais rencontré de blocage de volumétrie même en manipulant des arbres de plus 50000 Nodes.

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    624
    Détails du profil
    Informations personnelles :
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 624
    Points : 199
    Points
    199
    Par défaut
    Salut et merci pour cette info mais est-ce que les perfs ne vont pas en pâtir ?
    Dans un autre domaine j'utilise XPath aussi mais bon les perfs ne sont pas tellement bonne...

  4. #4
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 455
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 : 13 455
    Points : 24 867
    Points
    24 867
    Par défaut
    Pour les performances, le XML sera un plus lourd en terme de mémoire à cause de la structure objet mais si tu as des trous dans le données, tu y gagneras au final

    As-tu pensé à réduire les types, utiliser du Byte, Short au lieu du Integer si la plage de valeur n'est pas utile

    Une approche via TDictionary<Integer, ...> proche de l'arbo XML
    Si tu as beaucoup de trou mais de grand écart entre l'un le plus bas et le plus haut, le gain en mémoire sera considérable !
    Si tes tableaux sont complètement, alors il va falloir gérer un cache sur le DD ou voir comment fonctionner l'archi 64bits si tu peux dépasser les 2Go par process (3Go avec une option de Windows 32, j'ai pas le temps de chercher)

    Ensuite, j'ignore tes besoins de performances ou la durée de vie de données !
    Mais un MySQL Embedded pourrait gérer cela, avec un stockage non pas en matrice en mais ligne
    Et même les calculs seraient codés en SQL, et chose surprenante, cela pourrait être TRES rapide !
    Ce que sera lent sera la récupération des données, tant que tu lance des calculs qui reste sur le serveur comme des UPDATE, pas de soucis, par contre un SELECT avec des millions, là tu pourra prendre ton café ! évidemment il existe des Data Fetch intelligent améliorant cela !

    La syntaxe de lecture du TDictionary est la même par contre pour l'ajout c'est pas SetLengh mais une méthode Add ou AddOrSet

    Je te conseille de regrouper tes tableaux en record !
    Et ne faire un nombre réduit de Dictionnary

    Tu peux aussi faire ce travail déjà avec tes tableaux, par contre il faut bien gérer l'imbrication
    L'avantage, déjà avec les tableaux, c'est que tu peux faire le SetLength QUE lorsque c'est utile,
    si n'a pas de donnée à cette coordonné Row, RowCol, ColRow ou ClusterCol, tu économises la mémoire

    En gros, ça donnerait des structures imbriqués

    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
    Type
      TColIndex = Integer;
      TRowIndex = Integer;
      TClusterIndex = Integer;
     
      TColRow = record
        Matrix: Integer;
        Xij: Integer;
        T: Integer;
        Wij: Integer;
        ...
      end;
     
      TCol = record
        X_j: Integer; 
        Cj: Integer; 
        Tj: Integer
        ...
        Row: TDictionary<TRowIndex, TColRow>; 
      end;
     
      TClusterCol = record
        Bki: Integer;
        BestCTRki: Integer;
        BestGki: Integer;
      end;
     
      TCluster = record
        Clusters ...
        Mg
        BestWk
        BestBk
        Col: TDictionary<TRowIndex, TClusterCol>; 
      end;
     
      TDictionary<TColIndex, TCol>;
      TDictionary<TRowIndex, TRow>; 
      TDictionary<TClusterIndex , TCluster>;
    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

Discussions similaires

  1. Tableau dynamique à deux dimensions
    Par David Fouejio dans le forum MFC
    Réponses: 4
    Dernier message: 05/03/2007, 09h37
  2. [HashSet] Tableau dynamique à 2 dimensions
    Par ppopov dans le forum Collection et Stream
    Réponses: 5
    Dernier message: 21/01/2007, 16h21
  3. Réponses: 4
    Dernier message: 19/12/2006, 20h06
  4. declaration d'un tableau dynamique 2 dimensions
    Par mike600river dans le forum C++Builder
    Réponses: 4
    Dernier message: 22/05/2006, 08h53
  5. Réponses: 1
    Dernier message: 09/03/2006, 17h25

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