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

VB.NET Discussion :

Tableau 2 dimensions - gestion mémoire - limites


Sujet :

VB.NET

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Tooling - Testing
    Inscrit en
    Décembre 2008
    Messages
    141
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 77
    Localisation : Belgique

    Informations professionnelles :
    Activité : Tooling - Testing

    Informations forums :
    Inscription : Décembre 2008
    Messages : 141
    Par défaut Tableau 2 dimensions - gestion mémoire - limites
    Bonjour,

    J'ai une incompréhension dans la manière dont la mémoire se comporte, ou pour les règles des tableaux à deux dimensions,
    ou ??
    Voici

    PC en windows 10 en 64bits mémoire 8,00 Go
    Visual Studio 2017

    Je crée une application où je dois charger un grand nombre de données en mémoire et les traiter.
    Il s'agit en réalité d'un process LCS ( Longest Common Subsequence ) qui s'applique non pas à des chaînes de caractères, mais à des fichiers ; d'où le chargement en mémoire.

    Dans une application x64, je définit mon tableau ainsi

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     lmax = 40000
     rmax = 40000
     Dim LCS(lmax + 1 , rmax + 1 ) as integer
    J'ai un message erreur

    Une exception non gérée du type 'System.OutOfMemoryException' s'est
    produite dans LCS.exe
    Informations supplémentaires*: Les dimensions du tableau dépassent la
    plage prise en charge.
    Mais, et c'est là où c'est curieux, si je code

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     lmax = 20000
     rmax = 20000
     Dim LCS(lmax + 1, rmax + 1) As Integer
     '
     Dim LCS3(20000 + 1, 20000 + 1) As Integer
     Dim LCS4(20000 + 1, 20000 + 1) As Integer
     Dim LCS5(20000 + 1, 20000 + 1) As Integer

    Je n'ai pas de problème d'allocation.
    En termes de mémoire, et si je ne trompe pas, les deux sont équivalents.

    Information supplémentaire : après l'exécution du dernier code, je suis à 83% de mémoire avec quelques autres applications ouvertes et qui forcément consomment aussi.

    Une idée

    Merci

    Pierre

  2. #2
    Membre Expert Avatar de Phil Rob
    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2013
    Messages
    1 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2013
    Messages : 1 613
    Par défaut
    Bonjour,

    Je n'ai pas la solution à ton problème mais bien une remarque sur ta supposition "... et si je ne trompe pas, les deux sont équivalents" ...


    En VB, lors de la déclaration des tableaux, les paramètres de l'instruction DIM sont les valeurs maximales des INDICES.

    Ainsi, Dim LCS(40001, 40001) As Integer réserve de la mémoire pour une matrice dont les lignes sont indicées de 0 à 40001 et les colonnes de de 0 à 40001, soit une matrice de 40002 * 40002 positions, soit 1 600 160 004 Integer codés sur 4 octets (soit ± 6.5 Go).

    De même, LCS(20001, 20001) As Integer réserve de la mémoire pour une matrice dont les lignes sont indicées de 0 à 20001 et les colonnes de de 0 à 20001, soit une matrice de 20002 * 20002 positions, soit 400 080 004 Integer codés sur 4 octets (soit ± 1.5 Go).

    En répétant l'opération précédente pour LCS3, LCS4 et LCS5, ce sont des réservations de mémoire pour 4 matrices de ± 1.5 Go. Soit ± 6 Go. pour les 4 matrices.

    Ainsi Dim LCS(40001, 40001) As Integer occupe plus d'octets en mémoire que 4 fois LCS(20001, 20001) As Integer.

    Sauf erreur de ma part dans mes calculs ...


    J'espère que tu trouveras la solution à ton problème, notamment peut-être en utilisant un type numérique moins gourmant.
    Par exemple :
    Le type Short (ou Int16) occupe 2 octets et accepte les valeurs de -32 768 à 32 767
    Le type UShort (ou UInt16) occupe 2 octets et accepte les valeurs de 0 à 65 535
    Le type Byte occupe 1 octet et accepte les valeurs de -128 à 127
    Le type UByte occupe 1 octet et accepte les valeurs de 0 à 255

    Pense aussi aux valeurx maximales d'indice dont tu as vraiment besoin : 40002 * 40002 ==> 1 600 160 004. Mais s'il n'y a que 40000 lignes et 40000 colonnes, alors il faut limiter les indices max. à 39000. et 39000*39000 ==> 1 521 000 000, soit ± 80 000 000 valeurs de moins (± 320 Mo. s'il s'aguitn d'Integer).

    ...

  3. #3
    Membre confirmé
    Homme Profil pro
    Tooling - Testing
    Inscrit en
    Décembre 2008
    Messages
    141
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 77
    Localisation : Belgique

    Informations professionnelles :
    Activité : Tooling - Testing

    Informations forums :
    Inscription : Décembre 2008
    Messages : 141
    Par défaut
    Cher Maca,
    ( je ne sais plus d'où je tiens cela dans un coin de ma tête ! peut-être même pas exact )


    Merci pour la réponse.

    J'ai vite ajouté un nouveau
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     LCS6(20000 + 1, 20000 +1 ) as integer

    et cela tient. Il me reste encore de la mémoire.

    En outre, je dois garder as integer, car le tableau comprendra les occurances des enregistrements des deux fichiers chargés en mémoire.

    Comme j'ai dit il s'agit de traiter une séquence LCS dont le pseudo code est

    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
     
    # Find the index of the first mismatch top down
    for i = 1 to |F’|
     if F[i] = F’[i] then continue
     if F[i] <> F’[i] then break
    next
    # Files are identical
    if i = |F’| then return TextSpan(1,0)
    # Find the index of the first mismatch bottom up
    # Redefine F[j] to mean the 𝑗
    𝑡𝑕 character up from the bottom line
    for j = |F’| to i
     if F[j] = F’[j] then contine
     if F[j] <> F’[j] then break
    next
    if (j - i) > k then
     # Compile the entire file, they are too different
     return Textspan(1, |F’|)
    else
     # The change occurred between i and j
     return Textspan(i, j)
    end if
    ( exemple de Final Project Applied Algorithms - CSEP 521 - Chris Smith and Meher Malakapalli )



    WinDiff chez moi parvient à traiter deux fichiers de 700.000 enregistrements chacun.
    Je suppose qu'il fait cela en mémoire ( vu la rapidité du traitement ).

    Moi je n'y arrive pas .............. encore

    Je vais donc plancher ....

    Bonne soirée et encore merci

    Pierre

  4. #4
    Membre Expert Avatar de Phil Rob
    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2013
    Messages
    1 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2013
    Messages : 1 613
    Par défaut
    Cher Maca,
    ( je ne sais plus d'où je tiens cela dans un coin de ma tête ! peut-être même pas exact )
    "Maca" est une expression utilisée pour désigner les Wavriens (le Maca est la statue du gamin escaladant le perron de l'Hôtel de Ville de Wavre).
    Je ne suis pas Wavrien, mais j'en ai été proche (professionnellement) et j'habite la région. Alors, il y a peut-être un fond de vérité dans ce coin de ta tête

    Pour ce qui est de ton algo, j'en pige même pas l'énoncé ... mais je crois que les valeurs stockées dans ces tableaux sont des longueurs de chaines issues des fichiers. Dans ce cas, le type UShort (2 octets) devrait convenir : je ne crois pas que tu puisses trouver des chaines de 65 535 dans un des 700.000 enregistrements !

    Bonne soirée,


  5. #5
    Membre confirmé
    Homme Profil pro
    Tooling - Testing
    Inscrit en
    Décembre 2008
    Messages
    141
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 77
    Localisation : Belgique

    Informations professionnelles :
    Activité : Tooling - Testing

    Informations forums :
    Inscription : Décembre 2008
    Messages : 141
    Par défaut
    Encore merci.

    Je sais ce qu'est un Maca et pensais que vous en étiez un.... pas loin donc.

    Mon autre coin de tête va donc creuser, et chercher une solution à appliquer. Mémoire et méninges, même combat !

    Bien à vous

    Pierre

  6. #6
    Membre extrêmement actif
    Inscrit en
    Avril 2008
    Messages
    2 573
    Détails du profil
    Informations personnelles :
    Âge : 65

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 573
    Par défaut
    bonjour

    Commencons par le commencement : la memoire physique n'est pas en cause (la ram).c'est la memoire "virtuelle adressable" ,dite aussi espace d'adressage qui dépend des processus systeme (windows) ou programmes .
    processeur 32 bit : la memoire "virtuelle" adresssable est 2 GB
    processeur 64 bit : la memoire "virtuelle" adressable est 4 GB
    Cette memoire "virtuelle" adressable est donc gérée par le système(Windows)

    Cela veut dire concrètement :
    que les processus Windows 10(programmes ) sont divisées 2 camps :
    - processus 32 bits (programme 32 bits ) ne peuvent gérer qu'une mémoire "virtuelle adressable" au maximum de 2 Giga
    - processus 64 bits (programme 64 bits) ne peuvent gerer qu'une memoire "virtuelle adressable" au maximum de 4 Giga.

    Mais alors , c'est chiant me diras-tu car même si je compile mon programme en mode 64 bit ,j'aurais droit à un plantage OutMemory.
    Ah ben oui, ben non dira un bon normand .
    Il suffit de compiler ton projet en 64 bit (menu générer -> gestionnaire de configurations)
    D'ouvrir ton fichier app.config et y ajouter la section suivante (runtime) avec le jeton gcAllowVeryLargeObjects "activé":
    Code XML : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    ?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <runtime>
        <gcAllowVeryLargeObjects enabled="true" />
      </runtime>
      <startup>
            <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
        </startup>
     
    </configuration>
    Et voilà plus de OutOfMemory.....!!!!
    Pour comprendre ce qu'il fait voici l'explication ,il faut savoir qu'un processeur :
    - 32 bit peut générer des adresses mémoires pour accéder ses données "allant" de "zéro" à 2^31 -1 ( soit 2*147*483*647 soit # 2 giga octet)

    - 64 bit génère des adresses "allant" de "zéro" à 2^64 -1 ( soit 18*446*744*073*709*551*616 soit # 18*446*744*073 giga octet, c'est bigrement bigre ,presque "big"))
    Le jeton donnée active cette possibilité d'adressage 64 bit pour les programmes ou processus 64 bits, en exclusivité Film MGM (le lion dit-on chez moi !!!).

    code exemple behind.vb à compiler en 64 bits :
    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
    Imports System.Text
     
    Public Class Form1
        Private lmax As Integer = 40001
        Private rmax As Integer = 40001
        Private arr(lmax - 1, rmax - 1) As Integer
        Private arr2(1999, 1999) As Integer
        Private arr3(1999, 1999) As Integer
        Private sizeArr As Integer 'taille  en nombre d'elements
        Dim sizeMem As Single ' taille  en memoire
        Private sb As New StringBuilder
        Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
            sb.AppendLine("big arr")
            sizeArr = lmax * rmax
            sb.AppendLine(sizeArr.ToString())
            sizeMem = (sizeArr / 1000000000) * 8 'taille integer:8 octets
            sb.AppendLine(sizeMem.ToString() + "GigaOctets")
            'code  pour remplir le big array ici
            'For i As Integer = 0 To arr.GetUpperBound(0)
            '    For j As Integer = 0 To arr.GetLowerBound(0)
            '        arr(i, j) = 25
            '    Next
            'Next
            sb.AppendLine("small arr")
            sizeArr = 20000 * 20000
            sb.AppendLine(sizeArr.ToString())
            sizeMem = (sizeArr / 1000000000) * 8 'taille integer:8 octets
            sb.AppendLine(sizeMem.ToString() + "GigaOctets")
     
            TextBox1.Text = sb.ToString
     
        End Sub
    End Class
    Article MSDN qui explique tout cela sur ce lien :

    https://docs.microsoft.com/en-us/dot...tframework-4.0

    bon code....

  7. #7
    Membre Expert Avatar de Phil Rob
    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2013
    Messages
    1 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2013
    Messages : 1 613
    Par défaut
    Génial ! Merci Mabrouki.
    J'aurais dû y penser ... en réfléchissant un peu ...

    C'est bien là, la raison du problème de notre ami Pierre.
    Le système ne peut gérer des adressages jusqu'à 6 Go. mais il peut gérer de nombreux tableaux de 1.5 Go. Ce n'est pas le volume de données qui pose le problème ici, mais bien la taille des adresses.

    Et bien sûr, ça doit fonctionner en 64 bits.

    Très bonne journée à vous deux ...

  8. #8
    Membre confirmé
    Homme Profil pro
    Tooling - Testing
    Inscrit en
    Décembre 2008
    Messages
    141
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 77
    Localisation : Belgique

    Informations professionnelles :
    Activité : Tooling - Testing

    Informations forums :
    Inscription : Décembre 2008
    Messages : 141
    Par défaut
    Grand merci Mabrouki,

    Je connaissais "pas trop mal" les adressages 32bit et 64bit, c'est pour cela que j'ai compilé le programme x64 ( tout en étant en Windows 10 également ).
    Mais j'ignorais totalement ce paramètre du fichier config.

    Code XML : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    <runtime>
        <gcAllowVeryLargeObjects enabled="true" />
    </runtime>

    Pourquoi d'ailleurs cela n'est il pas fait automatiquement quand on choisit 64bit?

    Je pousse un soupir de soulagement, et comme le temps est ici au vent et à la pluie, je continue de développer ma petite application ECompD.

    Bonne journée et encore merci à vous deux.


    Pierre

Discussions similaires

  1. allocation mémoire tableau 2 dimensions
    Par imou222 dans le forum Débuter
    Réponses: 3
    Dernier message: 22/04/2014, 17h35
  2. Représentation mémoire tableau 2 dimensions
    Par stoner dans le forum Débuter
    Réponses: 5
    Dernier message: 16/04/2013, 20h52
  3. Réponses: 17
    Dernier message: 10/04/2013, 18h46
  4. Gestion d'un tableau à deux dimensions
    Par LadyArwen dans le forum ActionScript 1 & ActionScript 2
    Réponses: 1
    Dernier message: 05/10/2007, 11h30
  5. [D7] Tableau dynamique et Gestion mémoire
    Par Cl@udius dans le forum Langage
    Réponses: 7
    Dernier message: 13/03/2006, 15h16

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