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 C++ Discussion :

Overhead de mémoire lié à l'héritage


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Homme Profil pro
    Doctorant en Astrophysique
    Inscrit en
    Mars 2009
    Messages
    312
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Astrophysique
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2009
    Messages : 312
    Par défaut Overhead de mémoire lié à l'héritage
    Bonjour.

    Je bosse actuellement sur code C++ où j'essaye d'optimiser au mieux la consommation mémoire (c'est pour faire de l'astrophysique sur supercalculateurs). Donc comme souvent j'essaye de trouver le bon équilibre entre faire un code "lisible" pas trop horrible à utiliser, et optimiser partout où je peux (c'est tellement critique qu'il m'arrive de compacter plusieurs données qui tiennent sur quelques bits dans des "unsigned char"). Donc pour ne pas faire n'importe quoi, je voudrais être sûr de bien comprendre l'overhead de mémoire liée à l'héritage et aux membres virtuels.

    Je précise que ce qui m'intéresse c'est l'overhead par objet, l'overhead "static" par classe n'étant pas un problème pour moi.

    1) Est-ce que MaClasseB : public MaClasseA va ajouter un overhead mémoire si MaClasseA et MaClasseB ne comportent aucune méthode virtuelle ? (par exemple si MaClasseB se contente d'ajouter quelques fonctions à MaClasseA)

    2) Maintenant supposons que MaClasseA comporte n méthodes virtuelles : cela change-t-il quelque chose qu'elles soient pures ou non du point de vue de l'overhead mémoire (je ne pense que non, mais j'aimerai en être sûr) ?

    3) Toujours dans le cas où MaClasseA comporte n méthodes virtuelles : quel va être l'overhead pour chaque objet de type MaClasseB ? Un seul pointeur pour chaque objet indépendamment de n ? (+ un overhead static proportionnel à n dont je me fous un peu).


    4) Maintenant plus sioux, MaClasseC : public MaClasseA, public MaClasseB avec MaClasseA comportant nA méthodes virtuelles et MaClasseB comportant nB méthodes virtuelles. Quel est l'overhead pour chaque objet de type MaClasseC ?

    5) Et une dernière : MaClasseB : public MaClasseA et MaClasseC : public MaClasseB avec nA méthodes virtuelles dans A qui sont implémentées dans B ET dans C (donc celles qui sont appelées pour C "écrasent" celles de B) + nB méthodes virtuelles supplémentaires déclarées dans B qui sont implémentées dans C. Quel overhead pour chaque objet de type MaClasseC ?

    Merci infiniment à ceux qui m'aideront à y voir plus clair

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    Bonjour,

    loin d'en connaître long sur le sujet, il me semble que
    1- si aucune méthode n'est virtual, il n'y aura aucun overhead. Ca revient à avoir une seule classe qui implémente tout.
    2- à partir du moment où il y a des méthodes virtual, il ya création d'une vtable qui contient le pointeur vers la méthode réelle. Si les méthodes sont virtual pure ça n'y changera rien, ça bloquera uniquement la compilation si elle manque.


    J'ai trouvé ceci à ce sujet
    http://en.wikipedia.org/wiki/Virtual_method_table
    http://www.learncpp.com/cpp-tutorial...virtual-table/
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Membre émérite
    Avatar de Ekleog
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    448
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 448
    Par défaut
    1- Si la sous-classante ajoute des membres, il faudra essayer de compiler avec -Wpadding -Wpadded ou équivalent pour vérifier que l'alignement colle bien, et sinon, essayer de trouver un moyen pour organiser les membres dans le bon ordre.

    2- Au niveau de l'overhead pour quelle variable ? (virtuelle pure => non instanciable)

    3,4,5- Un pointeur sur fonction par fonction virtuelle par objet, je pense. Ou bien, peut-être, selon le compilo (peu probable), un int32 par objet, et après un lookup dans une table globale. (peu probable que le compilo suppose qu'il y aura moins de 65535 descendants) Il faudra essayer pour savoir, selon ton compilo. Au besoin, il est toujours possible d'émuler une vtable globale, mais ça risque de devenir lourd à gérer. Enfin, tu peux aller voir pour les projets C qui font de l'"héritage" avec des "fonctions virtuelles", pour savoir comment faire. (Il me semble que GCC fait ça, quelque part.) Mais je crois qu'ils font la technique du 1 pointeur / fonction / objet.

  4. #4
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Salut,
    En général les implémentations utilisent un vpointeur par 'chemin' d'héritage, i.e, ce n'est pas la profondeur de l'héritage qui compte mais sa largeur.
    Avec l'héritage virtuel, on a souvent en plus un pointeur en plus pour gérer les réajustements du pointeur this.
    En l'absence de fonctions virtuelles, il n'y a généralement pas d'impact (pas de vtable, pas de vpointeur).
    Le nombre de fonctions virtuelles n'a pas d'impact sur une instance. Comme tu le présents, ça n'impacte que la taille de la vtable qui est partagée par toutes les instances.
    virtuelle ou virtuelle pure n'impacte pas la taille de l'objet (ni la taille de la vtable d'ailleurs).

    Bien sûr tout cela peut varier d'un compilateur à l'autre et même selon les options de compilation.

    cf Implémentation des fonctions virtuelles. De mémoire, certains détails sont peut être approximatifs mais dans l'ensemble cela donne une idée de comment ça marche.

    Si cela s'y prête, tu peux faire du 'polymorphisme d'inclusion statique' avec le CRTP.

  5. #5
    Membre éclairé
    Homme Profil pro
    Doctorant en Astrophysique
    Inscrit en
    Mars 2009
    Messages
    312
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Astrophysique
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2009
    Messages : 312
    Par défaut
    Merci pour vos réponses.
    J'ai aussi eu l'occasion de regarder dans le bouquin "More Effective C++" ou tout cela est assez bien décrit.

    3D archi, merci pour le lien vers la FAQ sur le CRTP, je ne connaissais pas du tout et ça m'a l'air assez intéressant. De toutes façons, comme il y a une grosse partie de développement, pour l'instant je vais faire de l'héritage normal en gardant en tête les éventuelles optimisations futures qui seront nécessaires, et puis après je ferai peut être une version "low memory" si cela s'impose.

    J'ai fait quelques mesures sur des exemples simples et le vptr pèse 8 octets par objet sur les machines que j'utilise. C'est loin d'être négigeable !

    Par rapport à cette remarque :
    Ou bien, peut-être, selon le compilo (peu probable), un int32 par objet, et après un lookup dans une table globale. (peu probable que le compilo suppose qu'il y aura moins de 65535 descendants)
    , ce serait tellement bien qu'il y ait des options de compilations qui permettent de faire ce genre de chose. Passer de 8 octets à 2 (unsigned short int), serait quand même très appréciable (et ça m'éviterai d'avoir à faire une autre version "low memory"). Quelqu'un saurait-il si quelque chose de ce genre existe (je compile soit avec g++, soit avec intel icpc) ?

    Merci beaucoup.

  6. #6
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par Kaluza Voir le message
    J'ai fait quelques mesures sur des exemples simples et le vptr pèse 8 octets par objet sur les machines que j'utilise. C'est loin d'être négigeable !
    64 bits ?
    Si la variation de comportement est déterminée à la compilation, au delà de la pertinence de l'utilisation de l'héritage ou non tu auras quelque part une indirection et donc un pointeur. Tu ne fera donc pas mieux qu'un vpointeur et une vtable en terme de taille d'objet.
    Si la variation de comportement est totalement déterminée à la compilation, alors CRTP et autre approche générique pour garder un code OCP et permettre au codeur et au compilateur d'être plus efficace.


    Citation Envoyé par Kaluza Voir le message
    Par rapport à cette remarque :
    c'est juste une c..rie. Un vpointeur sera toujours plus efficace que n index sur une table globale.

  7. #7
    Membre éclairé
    Homme Profil pro
    Doctorant en Astrophysique
    Inscrit en
    Mars 2009
    Messages
    312
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Astrophysique
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2009
    Messages : 312
    Par défaut
    64 bits ?
    Vu qu'en général ce sont des machines avec au moins 10Tb de mémoire vive, c'est du 64 bits of course.

    c'est juste une c..rie. Un vpointeur sera toujours plus efficace que n index sur une table globale.
    J'utilise déjà la virtualité au minimum pour avoir le bon équilibre entre un code performant, lisible, maintenable et facilement extensible. Pour certaines applications c'est plutôt les perfs à l'exécution qui vont être recherchées, pour d'autre c'est plutôt l'occupation mémoire. Donc si il le faut, je ferais 2 versions : une "normale" et une "low memory", mais si une option de compilation me permettait de gagner 1TB facilement au détriment des perfs d'exécution je ne serais pas contre...

  8. #8
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Selon le contexte, certains compilateurs savent résoudre les appels des fonctions virtuelles et les transformer en appel statique (lorsqu'il n'existe par expl qu'une seule spécialisation de la fonction ou que seul des objets d'un type dérivé sont créés, etc.). Je ne sais pas jusqu'où peuvent aller ces optimisations pour réduire la taille des objets. La première chose est évidemment de travailler sur tes algos et tes types de données. Ensuite, ben, étudie ton compilateur. Lis sa doc et épluche toutes les options.

Discussions similaires

  1. Réponses: 22
    Dernier message: 31/07/2015, 10h28
  2. Gestion mémoire, héritage et cast
    Par Nemix dans le forum Langage
    Réponses: 9
    Dernier message: 24/01/2013, 11h50
  3. fichier mappé en mémoire
    Par WinBernardo dans le forum Delphi
    Réponses: 7
    Dernier message: 01/12/2006, 09h38
  4. Vitesse de la mémoire vidéo
    Par Anonymous dans le forum x86 16-bits
    Réponses: 3
    Dernier message: 06/06/2002, 20h20
  5. Problème avec la mémoire virtuelle
    Par Anonymous dans le forum CORBA
    Réponses: 13
    Dernier message: 16/04/2002, 16h10

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