Forum Programmation.c++ Classe / double et vitesse

Posté par  .
Étiquettes : aucune
0
4
nov.
2008
Bonjours à tous.
J'ai récuperé il y a quelques jours un code C++ écrit à la C (pas de classes, des passage par pointeurs, des malloc etc... Bref c'est juste que le code devait appeler certaines librairies écrite en C++ qu'il est C++)
Ce code étant plein de fuite de mémoire, j'ai ré-ecris son contenus sous forme d'une Classe C++
De plus j'ai utilisé des variable double au lieu de float ( simplement car j'utilise fftw qui prend en input des double)

Au niveau des bonnes nouvelles, je n'ai plus de fuite de mémoire, et j'arrive à garder une consommation mémoire très raisonnable.
Par contre j'ai perdu un facteur 2 en vitesse, en ayant globalement les mêmes fonctions juste organisé un peu différemment.

La bonne question est pourquoi ?

-Est ce que crée des classes les détruire et appeler des fonctions membre de classe est plus lent qu'appeler des fonctions ?
-Est ce que travailler en double précision est plus lent
-Est ce que en réglant une fuite de mémoire j'ai rajouter des delete qui prennent beaucoup de temps ?
-Est ce que c'est pas normal et que je devrais repenser la façon dont j'ai écris le code ?

Je précise que dans mon cas, la vitesse d'exécution est secondaire, et que de toute façon c'est long ( Traitement du signal avec plusieurs FFT par évènement soit en temps absolu 0.5 s par événement avec le vieux code contre 1 sec par evt avec le nouveau) . Par contre régler la fuite de mémoire me permet d'envisager un traitement massif de donnée sans tuer la machine...
  • # Quelques éléments

    Posté par  (site web personnel) . Évalué à 3.

    -Est ce que crée des classes les détruire et appeler des fonctions membre de classe est plus lent qu'appeler des fonctions ?

    Oui, si tu as des constructeurs qui font des choses qui étaient pas dans le code initial (des inits etc...). Idem pour les destructeurs (surtout si tu fais plus attention au fuites mémoire)

    Dans tous les cas gprof est ton ami pour savoir ce qui rame le plus (avec lui, j'ai fais parfois des optimisation x4 en voyant des goulots d'étranglements...)

    -Est ce que travailler en double précision est plus lent

    oui. Ca peut être très impactant. Tu aurais du d'abord porter en C++ avant de changer le comportement, pour voir.
    Fais un typedef dans le config.h et utilise que ce typedef pour pouvoir changer à un seul endroit ensuite tester

    -Est ce que en réglant une fuite de mémoire j'ai rajouter des delete qui prennent beaucoup de temps ?

    Peu.

    -Est ce que c'est pas normal et que je devrais repenser la façon dont j'ai écris le code ?

    Si après avoir passé de double à float tu as toujours une baisse de vitesse : oui. Le problème vient de toi.
    • [^] # Re: Quelques éléments

      Posté par  . Évalué à 3.

      Dans tous les cas gprof est ton ami pour savoir ce qui rame le plus (avec lui, j'ai fais parfois des optimisation x4 en voyant des goulots d'étranglements...)

      Valgrind avec l'outil callgrind est pas mal également, couplé avec kcachegrind pour exploiter les résultats.


      Étienne
    • [^] # Re: Quelques éléments

      Posté par  . Évalué à 2.

      -Est ce que crée des classes les détruire et appeler des fonctions membre de classe est plus lent qu'appeler des fonctions ?

      Oui, si tu as des constructeurs qui font des choses qui étaient pas dans le code initial (des inits etc...). Idem pour les destructeurs (surtout si tu fais plus attention au fuites mémoire)


      En ce qui concerne les appels, il y a une indirection supplémentaire si les méthodes sont virtuelles.

      En ce qui concerne la construction, si tu crées énormément d’objets, tu peux aussi faire attention aux initialisations des membres : préférer les initialisateurs aux affectations (syntaxe X(…) : mx(x) {} plutôt que X(…) { mx = x; }) et surtout éviter les recopies et les constructions inutiles (p.ex. mot-clef explicit pour les constructeurs de recopie, passage de paramètres en const&, etc.).
  • # Impact dans ...

    Posté par  (site web personnel) . Évalué à 3.

    -Est ce que crée des classes les détruire et appeler des fonctions membre de classe est plus lent qu'appeler des fonctions ?

    Oui, tu a 5 appels de fonction au lieu de 1 (en supposant que tu voulais dire objet, pas classe) :
    - malloc
    - constructeur
    - ta_fonction
    - destructeur
    - free

    Si tu n'as pas de constructeurs / destructeurs spécifiques, activer les optimisations du compilateur peut te permettre de regagner la performance perdue.

    -Est ce que travailler en double précision est plus lent

    C'est imperceptible sur un x86.

    -Est ce que en réglant une fuite de mémoire j'ai rajouter des delete qui prennent beaucoup de temps ?

    C'est pas impossible, un delete appelle une fonction supplémentaire, le destructeur, appelé souvent ça peut devenir mesurable.

    -Est ce que c'est pas normal et que je devrais repenser la façon dont j'ai écris le code ?

    Essaie aussi de comparer les 2 codes avec des optimisations du compilateur. Il est possible que l'écart ne soit plus le même. Si tu est sur un x86 32 bits, tu peux aussi compiler avec -mfpmath=sse -sse2 pour gagner en perfs.
  • # Re:

    Posté par  (site web personnel) . Évalué à 1.

    a- Est ce que crée des classes les détruire et appeler des fonctions membre de classe est plus lent qu'appeler des fonctions ?
    c--Est ce que en réglant une fuite de mémoire j'ai rajouter des delete qui prennent beaucoup de temps ?
    d-Est ce que c'est pas normal et que je devrais repenser la façon dont j'ai écris le code ?

    a- Seulement si:
    - tes objets ne vivent pas sur la pile, auquel cas tu peux payer une allocation dynamique que tu n'avais pas sinon
    - tu t'es amusé à rajouter des virtual sans raison -- i.e. si tu n'avais pas de vrai point de variation à l'endroit des appels de fonctions virtuelles.

    c- Si tu fais delete + new derrière en boucle ... tu pourrais consommer plus de temps que nécessaire.
    P.ex., pour des tableaux, il peut être plus efficace de bosser avec un vecteur et de provoquer des resize(), plutôt que de reconstruire à chaque boucle.

    d- Pour float vs double, je ne m'avancerai pas ; pour les options de compilation, j'imagine que tu utilises les mêmes partout ; l'utilisation des streams peut ralentir ; donc pour une simple conversion, il ne devrait pas y avoir d'impact.

    A tout hasard, cf le TR on C++ performances (n18015) sur le site du comité de standardisation.
  • # Quel sont tes options d'optimisation ?

    Posté par  . Évalué à 1.

    Lorsque je n'optimise pas, les fonctions et classes STL sont très lentes : Il suffit de se rendre compte de tout ce que la STL à a faire dès qu'on veut accéder à un élément d'un vecteur : il crée un itérateur avec (debut_du_tableau + index), qui lui appelle un operator+() qui lui construit un nouvel itérateur dont on appellera ensuite l'opérateur de déréférencement ...

    Avec -O ou -O2, gcc optimise tout ça et mon vecteur[i] ne va faire que l'opération qui va bien...

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.