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 :

Problème avec les allocateurs


Sujet :

C++

  1. #1
    Membre régulier
    Homme Profil pro
    Développeur .NET/C/C++
    Inscrit en
    Septembre 2007
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET/C/C++
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Septembre 2007
    Messages : 71
    Points : 122
    Points
    122
    Par défaut Problème avec les allocateurs
    Bonjour à tous,

    j'essaie actuellement d'implémenter une classe shared_vector, qui serait un mix entre un std::vector et un std::shared_ptr, l'idée étant que que lorsque je fais une copie de mon vector je ne fais qu'incrémenter un compteur de référence, et lorsque mon vector est détruit je décrémente ce compteur. Une fois que celui-ci atteint 0, les elements de mon vector sont alors détruit. (Rien de méchant jusqu'ici).
    J'aimerai pouvoir passer en paramètre template un type d'allocateur à utiliser pour effectuer les allocations de mémoire. Le hic, c'est que quand j'alloue de la mémoire, je dois pouvoir réserver de la mémoire pour stocker les éléments dans mon tableau + mon compteur de références. Or, l'interface des allocateurs ne permet que de reserver de la mémoire pour X éléments d'un type donné, mais ne permet pas de spécifier une quantité précise de mémoire à allouer.

    Qqun a une idée de comment je peux faire?
    "Toujours en faire plus pour en faire moins"

  2. #2
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 184
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 184
    Points : 17 118
    Points
    17 118
    Par défaut
    tu ne peux pas juste faire un vector de shared_ptr?
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  3. #3
    Membre chevronné Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 041
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 041
    Points : 2 228
    Points
    2 228
    Par défaut
    tu ne peux pas juste faire un vector de shared_ptr?
    ou plutôt un shared_ptr<std::vector<Element>>
    Or, l'interface des allocateurs ne permet que de reserver de la mémoire pour X éléments d'un type donné, mais ne permet pas de spécifier une quantité précise de mémoire à allouer.
    Il est facile de passer de l'un à l'autre:
    X*Element => X*sizeof(Element)
    Si tu veux que ton allocateur alloue de la mémoire disons 10octets... C'est simple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    struct Memory
    {
    unsigned char [10];
    };
    Tu passe ça en élément dans ton vector. Puis quand tu veux l'utiliser comme un autre élément tu le cast (Element*)MemoryPtr;Si tu veux que tes 10 octets soit aligné selon Element alors tu passes alignement en alignof(Element) et élément a alloué Memory
    Tu pourrais même : shared_ptr<std::vector<shared_ptr<Element>>>
    Homer J. Simpson


  4. #4
    Membre régulier
    Homme Profil pro
    Développeur .NET/C/C++
    Inscrit en
    Septembre 2007
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET/C/C++
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Septembre 2007
    Messages : 71
    Points : 122
    Points
    122
    Par défaut
    Citation Envoyé par Astraya Voir le message
    ou plutôt un shared_ptr<std::vector<Element>>
    Je pourrai, mais avoir un shared_vector est plus simple à l'utilisation. (En plus c'est potentiellement + performant)
    Il est facile de passer de l'un à l'autre:
    X*Element => X*sizeof(Element)
    Sauf qu'a ces X*sizeof(Element), je dois ajouter sizeof(ref_counter), et c'est bien là le problème.
    "Toujours en faire plus pour en faire moins"

  5. #5
    Membre chevronné Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 041
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 041
    Points : 2 228
    Points
    2 228
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Je pourrai, mais avoir un shared_vector est plus simple à l'utilisation. (En plus c'est potentiellement + performant)
    Laisse moi douter du fait que tu puisses faire plus performant sans y passé des mois

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Sauf qu'a ces X*sizeof(Element), je dois ajouter sizeof(ref_counter), et c'est bien là le problème.
    Donc shared_ptr<std::vector<Element>>
    Homer J. Simpson


  6. #6
    Membre régulier
    Homme Profil pro
    Développeur .NET/C/C++
    Inscrit en
    Septembre 2007
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET/C/C++
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Septembre 2007
    Messages : 71
    Points : 122
    Points
    122
    Par défaut
    Citation Envoyé par Astraya Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Je pourrai, mais avoir un shared_vector est plus simple à l'utilisation. (En plus c'est potentiellement + performant)
    Laisse moi douter du fait que tu puisses faire plus performant sans y passé des mois
    Fais gaffe, je serai capable d'en faire le pari
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Sauf qu'a ces X*sizeof(Element), je dois ajouter sizeof(ref_counter), et c'est bien là le problème.
    Donc shared_ptr<std::vector<Element>>
    Précisemment ce que je veux éviter.

    Petite remarque au passage:
    J'ai besoin de cela pour un projet perso, donc je ne cherche pas une solution rapide.
    Et si je pose la question, c'est aussi parce que je la trouve intéressante car elle mets en évidence une limitation des allocateurs actuels.

    Deuxième remarque:
    Hier je suis tombé là-dessus:
    http://en.cppreference.com/w/cpp/exp...emory_resource
    A priori c'est quelque chose de prévu pour C++17, aussi je me demande si ce n'est finalement pas là la solution à mon problème.
    "Toujours en faire plus pour en faire moins"

  7. #7
    Membre chevronné Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 041
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 041
    Points : 2 228
    Points
    2 228
    Par défaut
    Tu n'as pas l'air de te rendre compte de la complexité d'un simple sharde_ptr et d'un vector... Les dépendences cycliques, la gestion mémoire, la copie/move des éléments d'un vector ( car il faut considérer le meilleur car pour tout 'T'), l'alignement mémoire...
    Bref, shared_ptr<std::vector<Element>> ou fait le toi même mais t'étonne pas d'y être encore fin 2016. Sauf si tu te base sur du code opensource comme Boost ou autre..
    Homer J. Simpson


  8. #8
    Membre émérite
    Avatar de prgasp77
    Homme Profil pro
    Ingénieur en systèmes embarqués
    Inscrit en
    Juin 2004
    Messages
    1 306
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Eure (Haute Normandie)

    Informations professionnelles :
    Activité : Ingénieur en systèmes embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 306
    Points : 2 466
    Points
    2 466
    Par défaut
    Citation Envoyé par Astraya Voir le message
    Tu n'as pas l'air de te rendre compte de la complexité d'un simple sharde_ptr et d'un vector... Les dépendences cycliques, la gestion mémoire, la copie/move des éléments d'un vector ( car il faut considérer le meilleur car pour tout 'T'), l'alignement mémoire...
    Bref, shared_ptr<std::vector<Element>> ou fait le toi même mais t'étonne pas d'y être encore fin 2016. Sauf si tu te base sur du code opensource comme Boost ou autre..
    et je ne vois pas ce qu'une classe maison peut apporter de plus ... si ce n'est qu'un sucre syntaxique.

    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
    template<class Element>
    class shared_vector
    {
        std::shared_ptr<std::vector<Element> > _data;
    public:
        shared_vector() : _data(std::make_shared<std::vector<Element> >()) {}
        shared_vector(const shared_vector<Element>& other) : _data(other._data) {}
        shared_vector(shared_vector<Element>&& other) : _data(other._data)
        {
            other.reset(nullptr);
        }
        virtual ~shared_vector() {}
        shared_vector<Element> operator=(const shared_vector<Element>& other)
        {
            _data.reset(other._data);
        }
        shared_vector<Element> operator=(shared_vector<Element>&& other)
        {
            _data.reset(other._data);
            other.reset(nullptr);
        }
        const Element& operator[](std::size_t n) { return (*_data)[n]; }
        Element& operator[](std::size_t n) { return (*_data)[n]; }
        // autres méthodes de std::vector que l'on veut exposer...
    };
    Sous réserve de compilation.
    -- Yankel Scialom

  9. #9
    Membre régulier
    Homme Profil pro
    Développeur .NET/C/C++
    Inscrit en
    Septembre 2007
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET/C/C++
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Septembre 2007
    Messages : 71
    Points : 122
    Points
    122
    Par défaut
    Citation Envoyé par Astraya Voir le message
    Tu n'as pas l'air de te rendre compte de la complexité d'un simple sharde_ptr et d'un vector... Les dépendences cycliques, la gestion mémoire, la copie/move des éléments d'un vector ( car il faut considérer le meilleur car pour tout 'T'), l'alignement mémoire...
    Bref, shared_ptr<std::vector<Element>> ou fait le toi même mais t'étonne pas d'y être encore fin 2016. Sauf si tu te base sur du code opensource comme Boost ou autre..
    Ben si, je comprends bien toutes ces problématiques...
    Et puis si je dois bosser là-dessus jusque fin 2016 (mais j'en doute), pq pas? Après tout comme dit plus haut c'est pour un projet perso sans réel but et au final tout ce que je risque c'est d'apprendre des choses, donc je vois pas ou est le problème.
    Après, la raison pour laquelle le fait d'avoir un shared_vector<T> doit permettre d'aller plus vite est que cela permet d'accéder aux éléments en ne déréférençant qu'un seul pointeur, là ou un shared_ptr<vector<T>> va nécessiter d'en déréférencer 2.
    "Toujours en faire plus pour en faire moins"

  10. #10
    Membre régulier
    Homme Profil pro
    Développeur .NET/C/C++
    Inscrit en
    Septembre 2007
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET/C/C++
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Septembre 2007
    Messages : 71
    Points : 122
    Points
    122
    Par défaut
    Citation Envoyé par prgasp77 Voir le message
    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
    template<class Element>
    class shared_vector
    {
        std::shared_ptr<std::vector<Element> > _data;
    public:
        shared_vector() : _data(std::make_shared<std::vector<Element> >()) {}
        shared_vector(const shared_vector<Element>& other) : _data(other._data) {}
        shared_vector(shared_vector<Element>&& other) : _data(other._data)
        {
            other.reset(nullptr);
        }
        virtual ~shared_vector() {}
        shared_vector<Element> operator=(const shared_vector<Element>& other)
        {
            _data.reset(other._data);
        }
        shared_vector<Element> operator=(shared_vector<Element>&& other)
        {
            _data.reset(other._data);
            other.reset(nullptr);
        }
        const Element& operator[](std::size_t n) { return (*_data)[n]; }
        Element& operator[](std::size_t n) { return (*_data)[n]; }
        // autres méthodes de std::vector que l'on veut exposer...
    };
    Sous réserve de compilation.
    Bon allez, un p'tit correctif pour la route:
    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
     
    template<class Element>
    class shared_vector final
    {
        std::shared_ptr<std::vector<Element> > _data;
    public:
        //Ici, le ctor par défaut devrait suffire.
        shared_vector() : _data() {}
        shared_vector(const shared_vector<Element>& other) : _data(other._data) {}
        //Tant qu'à faire, autant utiliser le ctor de déplacement de shared_ptr. 
        shared_vector(shared_vector<Element>&& other) : _data(std::move(other._data))
        {
        }
        // pas la peine de mettre un dtor virtuel, vu que cette classe n'est pas censé etre héritée (j'ai d'ailleurs ajouté un "final" à cet effet)
        ~shared_vector() {}
        //Autant utiliser l'opérateur directement. Et au passage, renvoyer une ref plutot qu'une copie ;)
        shared_vector<Element>& operator=(const shared_vector<Element>& other)
        {
            _data = other._data;
            return *this;
        }
        // pareil.
        shared_vector<Element>& operator=(shared_vector<Element>&& other)
        {
            _data = std::move(other._data);
            return *this.
        }
        const Element& operator[](std::size_t n) { return (*_data)[n]; }
        Element& operator[](std::size_t n) { return (*_data)[n]; }
        // autres méthodes de std::vector que l'on veut exposer...
    };
    sous réserve de compilation, j' avoue ne pas avoir testé.
    "Toujours en faire plus pour en faire moins"

  11. #11
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Citation Envoyé par bountykiler Voir le message
    Ben si, je comprends bien toutes ces problématiques...
    Et puis si je dois bosser là-dessus jusque fin 2016 (mais j'en doute), pq pas? Après tout comme dit plus haut c'est pour un projet perso sans réel but et au final tout ce que je risque c'est d'apprendre des choses, donc je vois pas ou est le problème.
    Rien, ni personne ne t'en empêche, mais tu risques de te confronter à des difficultés auxquelles tu ne penses pas encore. Tu maitriseras le fonctionnement de std::vector et std::shared_ptr (si fait correctement ) mais ça va te prendre du temps.
    Citation Envoyé par bountykiler Voir le message
    Après, la raison pour laquelle le fait d'avoir un shared_vector<T> doit permettre d'aller plus vite est que cela permet d'accéder aux éléments en ne déréférençant qu'un seul pointeur, là ou un shared_ptr<vector<T>> va nécessiter d'en déréférencer 2.
    Si les accès sont séquentiels, un déréférencement de pointeur ça à un coût très faible. Ce qui coûte cher, c'est les caches misses.

    J'ai pas les nombres exacts, mais je suis prêt à parier que déréférencer un std::shared_ptr à un cout au moins 10 fois supérieur au déréférencement d'un pointeur nu, tout comme déréférencer un pointeur nu lors d'accès séquentiels doit être 50 à 100 fois plus rapide que lors d'accès aléatoires.

    Tant que tu n'as pas profilé ton code, l'optimisation à l'aveugle est inutile.

Discussions similaires

  1. Problème avec les fonctions
    Par jvachez dans le forum PostgreSQL
    Réponses: 1
    Dernier message: 13/01/2004, 13h06
  2. [Postgresql]Problème avec les fonctions ...
    Par fet dans le forum Requêtes
    Réponses: 4
    Dernier message: 02/10/2003, 10h04
  3. Problème avec les apostrophes
    Par misterbillyboy dans le forum Requêtes
    Réponses: 2
    Dernier message: 15/07/2003, 17h39
  4. Problème avec les fichiers .JPG
    Par cprogil dans le forum Langage
    Réponses: 5
    Dernier message: 10/06/2003, 16h44
  5. []Problème avec les formulaires Outlook
    Par davidinfo dans le forum Outlook
    Réponses: 6
    Dernier message: 05/12/2002, 10h59

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