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 :

Héritage, destructeurs et performances


Sujet :

Langage C++

  1. #1
    Membre expérimenté
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Points : 1 685
    Points
    1 685
    Par défaut Héritage, destructeurs et performances
    Bonsoir,

    je constate une nette perte de performances selon la manière dont je définis le destructeurs de mes classes de base et je ne comprends pas pourquoi.

    J'ai une classe de base Number,

    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
     
    #ifndef _NUMBER_HPP
    #define	_NUMBER_HPP
    /*! 
     * \class Number
     * \brief This is the base class for all real numbers (including integers).
     * \warning This class is not abstract so as to maintain good performance.
     */
    class Number
    {
    protected:
        /*!
         * \fn Number()
         * \brief default constructor
         * \warning this constructor MUST NOT be public
         */
        Number(){;};
    };
    ////////////////////////////////////////////////////////////////////////////////
    #endif	/* _NUMBER_HPP */
    dont hérite une classe générique Real<T> (à terminer) :
    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
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
     
    #ifndef _REAL_HPP
    #define	_REAL_HPP
    #include "Number.hpp"
    /*! 
     * \class Real
     */
    template<typename T>
    class Real : public Number
    {
    protected:
        /*! \brief value of the real number */
        T _value;
    protected:
        /*! \brief default construction */
        Real();
        /*! \brief copy construction */
        Real(T const&);
    public:
        /*! \brief assignement of a real number */
        T const& operator=(T const&);
        /*! \brief computation of the absolute value */
        double abs()const;
    public:
        /*! \brief comparison of two real numbers */
        template<typename TT>
        friend bool operator==(Real<TT>const&,Real<TT>const&);
        /*! \brief comparison of two real numbers */
        template<typename TT>
        friend bool operator==(TT const&,Real<TT>const&);
        /*! \brief comparison of two real numbers */
        template<typename TT>
        friend bool operator==(Real<TT>const&,TT const&);
        /*! \brief comparison of two real numbers */
        template<typename TT>
        friend bool operator<=(Real<TT>const&,Real<TT>const&);
        /*! \brief comparison of two real numbers */
        template<typename TT>
        friend bool operator<=(TT const&,Real<TT>const&);
        /*! \brief comparison of two real numbers */
        template<typename TT>
        friend bool operator<=(Real<TT>const&,TT const&);
        /*! \brief comparison of two real numbers */
        template<typename TT>
        friend bool operator>=(Real<TT>const&,Real<TT>const&);
        /*! \brief comparison of two real numbers */
        template<typename TT>
        friend bool operator>=(TT const&,Real<TT>const&);
        /*! \brief comparison of two real numbers */
        template<typename TT>
        friend bool operator>=(Real<TT>const&,TT const&);
        /*! \brief comparison of two real numbers */
        template<typename TT>
        friend bool operator<(Real<TT>const&,Real<TT>const&);
        /*! \brief comparison of two real numbers */
        template<typename TT>
        friend bool operator<(TT const&,Real<TT>const&);
        /*! \brief comparison of two real numbers */
        template<typename TT>
        friend bool operator<(Real<TT>const&,TT const&);
        /*! \brief comparison of two real numbers */
        template<typename TT>
        friend bool operator>(Real<TT>const&,Real<TT>const&);
        /*! \brief comparison of two real numbers */
        template<typename TT>
        friend bool operator>(TT const&,Real<TT>const&);
        /*! \brief comparison of two real numbers */
        template<typename TT>
        friend bool operator>(Real<TT>const&,TT const&);
    public:
        /*! \brief addition of two real numbers */
        template<typename TT>
        friend TT operator+(Real<TT>const&,Real<TT>const&);
        /*! \brief addition of two real numbers */
        template<typename TT>
        friend TT operator+(Real<TT>const&,TT const&);
        /*! \brief addition of two real numbers */
        template<typename TT>
        friend TT operator+(TT const&,Real<TT>const&);
        /*! \brief substraction of two real numbers */
        template<typename TT>
        friend TT operator-(Real<TT>const&,Real<TT>const&);
        /*! \brief substraction of two real numbers */
        template<typename TT>
        friend TT operator-(Real<TT>const&,TT const&);
        /*! \brief substraction of two real numbers */
        template<typename TT>
        friend TT operator-(TT const&,Real<TT>const&);
        /*! \brief multiplication of two real numbers */
        template<typename TT>
        friend TT operator*(Real<TT>const&,Real<TT>const&);
        /*! \brief multiplication of two real numbers */
        template<typename TT>
        friend TT operator*(TT const&,Real<TT>const&);
        /*! \brief multiplication of two real numbers */
        template<typename TT>
        friend TT operator*(Real<TT>const&,TT const&);
        /*! \brief division of two real numbers */
        template<typename TT>
        friend TT operator/(Real<TT>const&,Real<TT>const&);
        /*! \brief division of two real numbers */
        template<typename TT>
        friend TT operator/(TT const&,Real<TT>const&);
        /*! \brief division of two real numbers */
        template<typename TT>
        friend TT operator/(Real<TT>const&,TT const&);
    };
    ////////////////////////////////////////////////////////////////////////////////
    #include "Real.tcc"
    #endif	/* _REAL_HPP */
    Cette dernière classe sert à représenter les nombres réels (float,double,int,...) et utilise des méthodes en ligne pour rester proches des performances initiales des opérations élémentaires (+,-,*,/,...) sur les types numériques (float,double,int) :
    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
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
     
    #ifndef _REAL_TCC
    #define	_REAL_TCC
    template<typename T>
    inline Real<T>::Real()
    {}
    /*!
     * \fn Real(T const&)
     * \param value of a real number
     * \brief construction by value
     */
    template<typename T>
    inline Real<T>::Real(T const& value)
    :Number(),_value(value)
    {}
    ////////////////////////////////////////////////////////////////////////////////
    /*!
     * \fn inline T& operator=(T const&)
     * \param value of a real number
     * \brief assignement of a value
     */
    template<typename T>
    inline T const& Real<T>::operator=(T const& value)
    {
        return _value=value;
    }
    ////////////////////////////////////////////////////////////////////////////////
    /*!
     * \param left operand
     * \param right operand
     * \brief addition of two real numbers
     */
    template<typename TT>
    inline TT operator+(Real<TT>const& left,Real<TT>const& right)
    {
        return left._value+right._value;
    }
    ////////////////////////////////////////////////////////////////////////////////
    /*!
     * \param left operand
     * \param right operand
     * \brief addition of two real numbers
     */
    template<typename TT>
    inline TT operator+(Real<TT>const& left,TT const& right)
    {
        return left._value+right;
    }
    ////////////////////////////////////////////////////////////////////////////////
    /*!
     * \param left operand
     * \param right operand
     * \brief addition of two real numbers
     */
    template<typename TT>
    inline TT operator+(TT const& left,Real<TT>const& right)
    {
        return left+right._value;
    }
    ////////////////////////////////////////////////////////////////////////////////
    /*!
     * \param left operand
     * \param right operand
     * \brief substraction of two real numbers
     */
    template<typename TT>
    inline TT operator-(Real<TT>const& left,Real<TT>const& right)
    {
        return left._value-right._value;
    }
    ////////////////////////////////////////////////////////////////////////////////
    /*!
     * \param left operand
     * \param right operand
     * \brief substraction of two real numbers
     */
    template<typename TT>
    inline TT operator-(Real<TT>const& left,TT const& right)
    {
        return left._value-right;
    }
    ////////////////////////////////////////////////////////////////////////////////
    /*!
     * \param left operand
     * \param right operand
     * \brief substraction of two real numbers
     */
    template<typename TT>
    inline TT operator-(TT const& left,Real<TT>const& right)
    {
        return left-right._value;
    }
    ////////////////////////////////////////////////////////////////////////////////
    /*!
     * \param left operand
     * \param right operand
     * \brief multiplication of two real numbers
     */
    template<typename TT>
    inline TT operator*(Real<TT>const& left,Real<TT>const& right)
    {
        return left._value*right._value;
    }
    ////////////////////////////////////////////////////////////////////////////////
    /*!
     * \param left operand
     * \param right operand
     * \brief multiplication of two real numbers
     */
    template<typename TT>
    inline TT operator*(TT const& left,Real<TT>const& right)
    {
        return left*right._value;
    }
    ////////////////////////////////////////////////////////////////////////////////
    /*!
     * \param left operand
     * \param right operand
     * \brief multiplication of two real numbers
     */
    template<typename TT>
    inline TT operator*(Real<TT>const& left,TT const& right)
    {
        return left._value*right;
    }
    ////////////////////////////////////////////////////////////////////////////////
    /*!
     * \param left operand
     * \param right operand
     * \brief division of two real numbers
     */
    template<typename TT>
    inline TT operator/(Real<TT>const& left,Real<TT>const& right)
    {
        return left._value/right._value;
    }
    ////////////////////////////////////////////////////////////////////////////////
    /*!
     * \param left operand
     * \param right operand
     * \brief division of two real numbers
     */
    template<typename TT>
    inline TT operator/(TT const& left,Real<TT>const& right)
    {
        return left/right._value;
    }
    ////////////////////////////////////////////////////////////////////////////////
    /*!
     * \param left operand
     * \param right operand
     * \brief division of two real numbers
     */
    template<typename TT>
    inline TT operator/(Real<TT>const& left,TT const& right)
    {
        return left._value/right;
    }
    ////////////////////////////////////////////////////////////////////////////////
    #endif	/* _REAL_TCC */
    De la classe Real<double> hérite une classe DoubleReal représentant les flottants à précision double :
    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
     
    #ifndef _DOUBLEREAL_HPP
    #define	_DOUBLEREAL_HPP
    #include "Real.hpp"
    /*! 
     * \class DoubleReal
     */
    class DoubleReal : public Real<double>
    {
    public:
        DoubleReal(double const&);
    };
    ////////////////////////////////////////////////////////////////////////////////
    #include "DoubleReal.tcc"
    #endif	/* _DOUBLEREAL_HPP */
    Le fichier DoubleReal.tcc est aussi vide que DoubleReal.hpp :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    #ifndef _DOUBLEREAL_TCC
    #define	_DOUBLEREAL_TCC
    inline DoubleReal::DoubleReal(double const& value)
    :Real<double>(value)
    {}
    #endif	/* _DOUBLEREAL_TCC */
    Lorsque je mesure le temps mis pour faire plusieurs sommes de doubles, par exemple avec le code
    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
     
    #include <cstdlib>
    #include <iostream>
    #include "Dataset.hpp"
    #include "KMeans.hpp"
    #include "Profiler.hpp"
    #include "DoubleReal.hpp"
    /*
     * 
     */
    int main() {
     
        double a = 1.0;double b = 2.0;
     
        unsigned int m=100000;
        unsigned int n=100000;
        Profiler prf; // classe permettant de mesurer le temps CPU
        double tmps = prf.cputime();
        for (size_t i=0;i<m;++i)
        {
            for (size_t j=0;j<n;++j)
                a=a+b+b;
        }
        tmps = prf.cputime()-tmps;
     
        std::cout<<"elapsed CPU time : "<<tmps<<std::endl;
     
     
        return (EXIT_SUCCESS);
    }
    j'obtiens 4 secondes de calcul (g++ -O3).
    Si je remplace la ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    double a = 1.0;double b = 2.0;
    par la ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    DoubleReal a = 1.0;DoubleReal = 2.0;
    je mesure le même temps.

    La mauvaise nouvelle est que je n'ai pas déclaré de destructeur dans les classes Number et Real<T>. J'imagine que par défaut ils sont privés et non virtuels alors qu'ils devraient être publics et virtuels ou protégés et non virtuels si j'en crois l'article de la faq.

    Saut que si je déclare ces destructeurs autrement, je perds énormément en performances. Par exemple, pour la classe Number, si j'ajoute
    mon temps de calcul passe de 4 secondes à 54 secondes!!!
    C'est d'ailleurs pour cela que mes constructeurs sont déclarés protégés dans les classes Number et Real<T>... mais j'aurais préféré faire des classes abstraites.

    Quelqu'un sait-il comment contourner le problème?

  2. #2
    Membre expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Points : 3 344
    Points
    3 344
    Par défaut
    1. Quel compilateur utilises-tu?
    2. Est-ce que tu mesures les performances en mode Debug?

  3. #3
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 629
    Points : 30 692
    Points
    30 692
    Par défaut
    Salut,

    A vrai dire, je me demande honnêtement s'il est réellement opportun d'essayer de faire hériter ta classe template Real<T> de number...

    Si on peut, effectivement, dire que tout réel est un nombre (du moins au sens mathématique du terme), et que l'on peut en dire autant pour les entiers, l'héritage n'aurait, à l'extrême limite, un intérêt que dans le sens où... tu voudrais faire cohabiter des entiers et des réels dans une même collection en les faisant passer pour... des nombres.

    Le problème, c'est que ta classe nombre, elle n'est pas vraiment très utile dans cette optique, au vu de sa forme actuelle

    Et il ne faut pas oublier les incompatibilités dues aux limites des différents types de valeurs numérique, qu'il sera difficile de gérer (faire entrer un short dans un int, c'est pas un problème, mais faire rentrer un int dans un short, ca nous fait perdre des informations )

    Tu ne pourrais t'en sortir, aussi bien pour récupérer les fonctions / opérateurs intéressants que pour éviter les incompatibilités de types qu'à coup de downcast... Est-il utile de te rappeler que c'est rarement une solution

    Il y aurait bien sur la solution de passer par un patern visiteur, pour autant que cela ait un sens
    Tu pourrais donc avoir quelque chose comme
    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
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    class Visitor;
    class Number
    {
        public:
            virtual void accept(Visitor const & v) const = 0;
            virtual ~Number() = 0;
    };
    Number::~Number(){}
    template <class T>
    class Real :public Number
    {
        public:
            typedef T value_type;
            Real(T t):t_(t){}
            ~Real(){}
            void accept(Visitor const &) const;
            value_type value() const{return t_;}
        private:
            T t_;
    };
    class Visitor
    {
        public:
            void visit(Real<double> const & r) const
            {
                std::cout<<"this use a double :"<<r.value()<<std::endl;
            }
            void visit(Real<float> const & r) const
            {
                std::cout<<"this use a float :"<<r.value()<<std::endl;
            }
            void visit(Real< long double> const & r) const
            {
                std::cout<<"this use a long double :"<<r.value()<<std::endl;
            }
    };
    template<typename T>
    void Real<T>::accept(Visitor const & v) const
    {
        v.visit(*this);
    }
    typedef Real<float> FloatReal;
    typedef Real<double> DoubleReal;
    typedef Real<long double> LongDoubleReal;
    struct Deleter
    {
        void operator()(Number *t)
        {
            delete t;
        }
    };
    struct VisitIt
    {
        VisitIt(Visitor const & v):v(v)
        {
     
        }
        template<typename T>
        void operator()(T * ptr)
        {
            ptr->accept(v);
        }
        Visitor const & v;
    };
    int main()
    {
        std::vector<Number*> tab;
        tab.push_back(new FloatReal(12.123));
        tab.push_back(new DoubleReal(45.456));
        tab.push_back(new LongDoubleReal(78.123));
        Visitor v;
        std::for_each(tab.begin(), tab.end(),VisitIt(v));
        std::for_each(tab.begin(), tab.end(), Deleter());
        return 0;
    }
    Mais, pour ce qu'il en est des opérateur mathématiques...

    N'oublie pas que l'héritage publique est généralement incompatible avec la sémantique de valeur, qui est nécessaire pour pouvoir les implémenter

  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
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    Je suis surpris mais comme Klaim je me demande quelle version de gcc tu utilises et quelles sont tes options de compilation ?
    Si j'en suis la logique de ce que tu as déjà fait, passes en protégé ton destructeur dans la classe Number et inline public dans DoubleReal.

  5. #5
    Membre expérimenté
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Points : 1 685
    Points
    1 685
    Par défaut
    Bonjour,

    merci à tous pour vos réponses.

    Le compilateur :

    j'utilise g++ avec le tag d'optimisation -O3.
    La distribution est celle de MinGW.
    En mode debug, c'est encore pire puisque je perds en performances quoi que je fasse (normal!).
    J'ai essayé d'autres tags (-O,-O2) mais c'est -O3 le meilleur.

    Passer le destructeur de Number en protégé :

    en déclarant le destructeur de Number, mes temps de calcul explosent...

    Faire hériter des classes de Real<T> :

    La classe Real<T> n'est pas destinée à être instanciée (constructeurs protégés mais il en manque si j'ai bonne mémoire).
    Elle me sert juste à ne pas faire des copier-coller des opérateurs +,-,=,etc pour chaque type numérique (int,float,double,...).
    M'arrêter à la classe Real<T> me gêne aussi parce que je veux contrôler un minimum le type T (pour moi Real<double*> n'a pas de sens).

    Si je comprends bien, il serait finalement plus logique d'écrire chaque classe (DoubleReal,DoubleComplex,Integer,etc) quitte à perdre du temps?

    Incompatibilité entre types numériques différents :

    oui, effectivement je suis au courant pour short et int, etc.
    A priori, je n'aurai pas besoin de transtyper.

    Pattern visiter :

    très mauvaise solution pour moi car tu déclares Number en classe abstraite : je perds énormément en performances.


    En clair, si je ne laisse pas le compilateur s'occuper seul des destructeurs, je suis perdant même en utilisant le mot-clé inline.
    Si je comprends bien, l'idée selon vous est de ne pas faire d'héritage pour les sémantiques de valeur (Real<T> disparaît).
    J'ai du boulot!

    Par contre, ça ne résout pas forcément mon problème de perfs.
    Je vais vérifier.

  6. #6
    Membre expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Points : 3 344
    Points
    3 344
    Par défaut
    Tu peux préciser la version de GCC/Mingw stp?

    Si quelqu'un a les moyen de tester, ça ressemble énormément a un "bug" de compilateur.

    Au passage, si tu ne mets pas le ; dans le destructeur est-ce que tu retrouves les performances "normales"?

  7. #7
    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
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    Citation Envoyé par Klaim Voir le message
    Tu peux préciser la version de GCC/Mingw stp?

    Si quelqu'un a les moyen de tester, ça ressemble énormément a un "bug" de compilateur.

    Au passage, si tu ne mets pas le ; dans le destructeur est-ce que tu retrouves les performances "normales"?
    Je suis aussi très surpris des résultats.
    @Aleph : As tu un exemple complet qu'on puisse le passer au grill ?
    As-tu essayé avec un autre compilateur (par expl, visual C++ Express qui est gratuit et rapidement installable) ?
    Citation Envoyé par Aleph69 Voir le message
    Faire hériter des classes de Real<T> :

    La classe Real<T> n'est pas destinée à être instanciée (constructeurs protégés mais il en manque si j'ai bonne mémoire).
    Elle me sert juste à ne pas faire des copier-coller des opérateurs +,-,=,etc pour chaque type numérique (int,float,double,...).
    M'arrêter à la classe Real<T> me gêne aussi parce que je veux contrôler un minimum le type T (pour moi Real<double*> n'a pas de sens).
    Cf Barton–Nackman trick : l'héritage est privé et non public enlevant ainsi ton soucis de destructeur.

  8. #8
    Membre expérimenté
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Points : 1 685
    Points
    1 685
    Par défaut
    Bonjour,

    La version de MinGW est 5.1.6.
    Pour la version de g++, j'obtiens ça sous dos :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    C:\MinGW\bin>g++ --version
    g++ (GCC) 3.4.5 (mingw-vista special r3)
    Copyright (C) 2004 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    Pour l'exemple complet, je vais archivé une version light et la poster dans la soirée.

    De mon côté, je vais tester avec visual, ça sera une bonne occasion de l'essayer.

  9. #9
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    La branch 3.4 a vu jésus... essaye de trouver une version de mingw avec un gcc plus récent. :/

  10. #10
    Membre expérimenté
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Points : 1 685
    Points
    1 685
    Par défaut
    Bonsoir,

    merci pour l'info goten!
    Effectivement, il semble que ma version date si j'en crois une précédente discussion sur le sujet...
    Ce qui est bizarre, c'est que la version de MinGW que j'utilise ici a été téléchargée... aujourd'hui!

    Je vais regarder tout cela de plus pres, je refais mes tests et je vous tiens au courant.

  11. #11
    Membre expérimenté
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Points : 1 685
    Points
    1 685
    Par défaut
    Lu sur la page officielle de MinGW :

    Automated Installer
    The mingw-get installer currently installs only GCC 3. You will get GCC 3 using this method.
    If you want to install the latest GCC release, use the Manual Installation method above.
    Bon, c'est parti pour une installation manuelle!

  12. #12
    Membre éclairé Avatar de MatRem
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    750
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 750
    Points : 693
    Points
    693
    Par défaut
    Tu pourras installer gcc 4.5 avec un mingw manuel, mais tu auras aussi vite d'installer une ubuntu

  13. #13
    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
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    TDM GCC une autre version de mingw mais mise à jour plus fréquemment.

  14. #14
    Membre expérimenté
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Points : 1 685
    Points
    1 685
    Par défaut
    Bonsoir,

    j'ai désinstallé MinGW et installé TDM-GCC : ça ne résout pas le problème.

    J'ai mis en fichiers joints les sources si certains veulent tester.
    Il faut comparer les performances entre les DoubleReal et les double dans le fichier newmain.cpp en commentant/décommentant la ligne de déclaration/initialisation adéquate :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    DoubleReal a=2.0;    DoubleReal b=1.0;
        //double a = 1.0;double b = 2.0;
    Par défaut, il n'y a pas de différence de perfs entre DoubleReal et double.
    C'est parce que le destructeur de Number n'est pas déclaré.
    Il y a une ligne à décommenter dans Number.hpp pour avoir le destructeur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    //~Number(){};  /* a decommenter pour tester avec destructeur */
    Alors les perfs devraient normalement être différentes chez vous aussi.

    Dans le fichier principal, la classe Profiler ne mesure le temps CPU que sur les machines Windows :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    Profiler prf;
        double tmps = prf.cputime();
        for (size_t i=0;i<m;++i)
        {
            for (size_t j=0;j<n;++j)
                a=a+b+b;
        }
        tmps = prf.cputime()-tmps;
     
        std::cout<<"elapsed CPU time : "<<tmps<<std::endl;
    Cependant, elle n'est pas très utile : il suffit de régler correctement les paramètres de boucle m et n pour avoir une différence de temps significative.

    Merci d'avance pour votre aide!

  15. #15
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 861
    Points
    11 861
    Par défaut
    Sinon, conceptuellement, ce qui collerait mieux ça serait de définir (explicitement ou implicitement) un "concept" Number (ils sont pas dans le langages mais tu peux toujours émuler ça). Car ça vérifiera les prérequis à la compilation (plutôt qu'à l'exécution comme avec l'héritage) et c'est ce qui est le plus proche de la pensée mathématique qu'on en a. C'est pas quand tu fais un calcul que tu sais que la multiplication de deux réels renvoie un réel, tu le sais de par la définition de la multiplication sur les réels.

  16. #16
    Membre expérimenté
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Points : 1 685
    Points
    1 685
    Par défaut
    Merci pour votre suggestion Alp.
    En fait, je ne suis pas particulièrement attaché à ma conception et je conçois tout à fait qu'elle ne soit pas du tout optimale et sûrement très naïve.
    J'ai encore le mauvais réflexe de penser mes objets à partir de leurs propriétés mathématiques plutôt qu'en fonction de leur comportement informatique.
    Je suis typiquement un violeur de LSP : si je l'avais pas lu dans la faq, j'aurais très bien pu faire hériter une classe Carré d'une classe Rectangle...


    L'enjeu de mon post se situe plutôt au niveau des performances.
    Si je ne peux pas faire hériter des classes avec des destructeurs explicites sans multiplier mes temps de calcul par 10, je ne vois plus bien l'intérêt du C++ en ce qui me concerne.

    Je me doute qu'il doit y avoir un problème mais je ne vois pas lequel.
    La version trop ancienne du compilateur me paraissait être une bonne piste mais apparemment ce n'est pas cela.

    @3DArchi : j'ai oublié de tester avec Visual. Je vous tiens au courant!

  17. #17
    Membre expérimenté
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Points : 1 685
    Points
    1 685
    Par défaut
    Bonjour,

    je viens de tester brièvement avec Visual en utilisant les options d'optimisation.
    Premièrement, c'est ultra rapide : beaucoup mais alors beaucoup plus qu'avec g++.
    En fait c'est tellement rapide que je n'arrive même pas à mesurer correctement le temps CPU (de l'ordre de 1e-6 secondes).
    Même en ajoutant une boucle ça ne change rien.

    Je peux déclarer le destructeur de Number sans problèmes.
    Par contre, dès que je le déclare virtuel, le code redevient très lent (aussi lent qu'avec g++).

    Je vais modifier mes tests pour avoir des temps significatifs sans destructeur déclaré.

  18. #18
    Invité
    Invité(e)
    Par défaut
    Bonjour,
    J'ai un peu de mal à comprendre. Ce sujet constitue-t-il un banc d'essai de performance, de compilateurs, de ce que représente précisément un réel, les relations entre la logique mathématique et la réalité informatique, ou autre-chose ?
    En effet, la classe NUMBER semble avoir pour but de traiter indifféremment les int, les float, les double. Cela me semble tout à fait contraire à la logique d'un langage. Un langage est destiné à servir d'interface entre l'utilisateur et la machine. Si l'utilisateur déclare une variable int, c'est parce qu'il a besoin d'une variable entière entre -32 768 et 32767 (16 bits); il en est de même pour les autres types.
    Les calculettes ne disposent pas de ce choix. Voudrait-on dispenser le programmeur de cette obligation de prise de décision?

    Si ce sujet rentre dans le cadre d'un étude théorique sur les langages, avec en particulier la création d'une classe NUMBER qui englobe tout ce qui n'est pas alphabétique, il devrait être dans un forum "Recherche".

    Vous cherchez à activer un destructeur. Soit, vous avez un constructeur, il est logique d'avoir un destructeur. D'abord, je n'ai pas vu d'opérateur new, donc le destructeur par défaut devrait, à mon avis, être appelé, et ensuite, qu'y a-t-il à faire dans ce destructeur ? Je n'ai pas vu d'allocation mémoire à libérer ou des choses comme ça.

  19. #19
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Peu importe ce qu'il y aura dans le destructeur, avec la relation d'héritage actuelle il se retrouve obligé de le déclarer (soit pour le mettre virtuel soit pour l'interdire).

  20. #20
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par Aleph69 Voir le message
    je viens de tester brièvement avec Visual en utilisant les options d'optimisation.
    Premièrement, c'est ultra rapide : beaucoup mais alors beaucoup plus qu'avec g++.
    En fait c'est tellement rapide que je n'arrive même pas à mesurer correctement le temps CPU (de l'ordre de 1e-6 secondes).
    Même en ajoutant une boucle ça ne change rien.
    Et si tu affiches le résultat du calcul dans le main, il se passe quoi ?

Discussions similaires

  1. Héritage SQL et performances
    Par BigFoot69 dans le forum Décisions SGBD
    Réponses: 17
    Dernier message: 18/04/2014, 17h16
  2. héritage et destructeurs virtuels.
    Par deubelte dans le forum C++
    Réponses: 19
    Dernier message: 08/04/2010, 10h42
  3. [MLD] Héritage et performances
    Par ymoreau dans le forum Schéma
    Réponses: 8
    Dernier message: 09/07/2009, 09h35
  4. Gotw #5 héritage et destructeur virtual
    Par Trunks dans le forum Langage
    Réponses: 7
    Dernier message: 07/04/2009, 14h56
  5. Thread, Héritage et Destructeurs
    Par contremaitre dans le forum Threads & Processus
    Réponses: 8
    Dernier message: 15/09/2008, 10h20

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