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

C++ Discussion :

Alignement mémoire avec GCC


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Par défaut Alignement mémoire avec GCC
    Bonjour,

    Je cherche à réduire la mémoire de mon application qui alloue très souvent une structure (disons Test dans notre exemple) en heap.
    Voilà un mini-code qui montre le soucis :
    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
    #include <windows.h>
    #include <psapi.h>
    #include <iostream>
     
    static size_t getMemoryConsuption() {
        PROCESS_MEMORY_COUNTERS pmc;
        GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc));
        return pmc.WorkingSetSize;
    }
     
    struct Test {
        uint32_t* pointer; // 4 bytes
        unsigned char data; // 1 byte
    }__attribute__((__packed__));
     
    int main() {
        std::cout << sizeof(Test) << std::endl;
        for (unsigned int i=0; i<10000000; i++)
        {
            Test* n = new Test();
            n->data = 0;
        }
        std::cout << "getMemoryConsuption  = " << getMemoryConsuption()/(1024*1024) << " MB" << std::endl;
        system("pause");
        return 0;
    }
    En mettant __attribute__((__packed__)), j'ai bien 5 bytes comme taille pour ma structure Test au lieu de 8 (à cause du padding de structure).

    Mais c'est bizarre, en RAM quand je vérifie avec l'API windows et la fonction getMemoryConsuption(), j'ai 157 MB alloué pour 10 000 000 pointeurs sur Test.

    Si j'enlève __attribute__((__packed__)), ma structure Test a donc une taille de 8 bytes mais j'ai quand même 157 MB alloué en RAM.

    Pire encore, si j'enlève le membre data de la structure, la structure devient alignée sans avoir besoin de __attribute__((__packed__)) et a donc une taille de 4 octets. Et bien, j'ai aussi 157 MB de RAM alloué dans ce cas...

    Je compile en 32 bits sous Windows 10 avec GCC 4.9.2 (TDM-1)

    Qu'est ce qui se passe ?

    Merci d'avance
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  2. #2
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    L'opérateur new doit allouer de la mémoire qui fait à minima la taille souhaitée et est alignée à minima à l'alignement nécessaire.
    Au moment de la réservation, il doit aussi réserver des données supplémentaires pour sa gestion interne (au moins un pointeur et un size_t alignés).
    Pour éviter un phénomène dit "gruyère" les réservations ont aussi une taille minimum et un alignement minimum.

    Donc ici quelle que soit la taille de la structure (4,5 ou 8 octets), il y réservation de 32 octets.
    Essaie de réserver des tableaux de 10 Test, la consommation mémoire dépendra alors plus de la taille de Test.

  3. #3
    Membre Expert
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Par défaut
    Citation Envoyé par dalfab Voir le message
    L'opérateur new doit allouer de la mémoire qui fait à minima la taille souhaitée et est alignée à minima à l'alignement nécessaire.
    Au moment de la réservation, il doit aussi réserver des données supplémentaires pour sa gestion interne (au moins un pointeur et un size_t alignés).
    Pour éviter un phénomène dit "gruyère" les réservations ont aussi une taille minimum et un alignement minimum.

    Donc ici quelle que soit la taille de la structure (4,5 ou 8 octets), il y réservation de 32 octets.
    Essaie de réserver des tableaux de 10 Test, la consommation mémoire dépendra alors plus de la taille de Test.
    Oui je me doutais bien que le new devait faire des réservations supplémentaires, c'est bien ce que je craignais

    Je ne peux pas allouer des tableaux de Test car j'ai besoin de pointeurs donc à la rigueur, un tableau de pointeurs comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    for (unsigned int i=0; i<1000000; i++)
        {
            Test** n = new Test*[10];
            for (unsigned int k=0; k<10; k++)
            {
                n[k] = new Test();
                n[k]->data = 0;
            }
        }
    Mias le problème est toujours le meme, ca ne dépend pas de la taille de Test...

    Une idée ?
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  4. #4
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Et,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
       Test* alls = new Test[1000000];
     
       for (unsigned int i=0; i<1000000; i++)
       {
                n[i] = alls + i;
                n[i]->data = 0;
       }

  5. #5
    Membre Expert
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Par défaut
    Hum c'est quoi la variable n dans ton exemple ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Test* alls = new Test[1000000];
    Et ce n'est pas un tableau de pointeurs mais un tableau de structure non ?

    PS: Bonnes fêtes de Noel
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  6. #6
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Citation Envoyé par Aspic Voir le message
    Hum c'est quoi la variable n dans ton exemple ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Test* alls = new Test[1000000];
    Et ce n'est pas un tableau de pointeurs mais un tableau de structure non ?

    PS: Bonnes fêtes de Noel
    n c'est ta variable pointeur, ce qui permet d'avoir un tableau de pointeurs qui pointent tous vers le tableau de structures. C'est le seul moyen d'avoir des pointeurs et de limiter le surcoût du système d'allocation.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Test** n = new Test*[100000];
    Joyeuses fêtes à tous.

Discussions similaires

  1. Allouer un segment de mémoire avec "GNU GCC Compiler&qu
    Par damien99 dans le forum Autres éditeurs
    Réponses: 2
    Dernier message: 22/06/2006, 23h18
  2. adressage mémoire avec gcc
    Par fraisdos dans le forum C
    Réponses: 4
    Dernier message: 29/09/2005, 15h29
  3. define avec GCC.
    Par vagabon dans le forum Autres éditeurs
    Réponses: 4
    Dernier message: 12/06/2003, 14h04
  4. les .a avec gcc
    Par Groove dans le forum Autres éditeurs
    Réponses: 4
    Dernier message: 31/03/2003, 07h59
  5. getch() avec gcc
    Par Jorus dans le forum Autres éditeurs
    Réponses: 5
    Dernier message: 16/12/2002, 14h47

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