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 :

performance des 'cast'


Sujet :

C++

  1. #21
    Expert confirmé
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 526
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 526
    Par défaut
    Citation Envoyé par bricerive
    (Pour ceux qui voient vraiment pas comment ca peut marcher, au point de croire que ca marche pas, je ne saurais trop recommander de faire un essai)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
        dlong.d = val + D2I_CONVERSION_FACTOR;
    }
    Je suis très très sceptique sur le fait que cela soit plus performant

    Citation Envoyé par JolyLoic
    Parmi les inconvénients de cette méthode, j'ajouterai :
    - Aucune garantie que ça fasse quoi que ce soit. Ecrire dans un membre d'une union et lire dans un autre est un comportement indéfini. Il se peut que ça marche sur une certaine machine, avec une certaine version d'un compilateur, avec certaines options de compilation, pendant certaines phases de la lune, mais rien n'est moins sur.
    100% d'accord mais quel est le rapport avec les phases de la lune ?

  2. #22
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Citation Envoyé par thewho
    JolyLoic m'avait demandé mon code de test, le voici:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    [...]
    #include <iostream>
        double d = -12345.1234665;
        int n1 = 0, n2 = 0;
     
        // boucle utilisant "l'astuce" d2i
     
        QueryPerformanceCounter(&t1);
        for (int i=0;i<NB;++i)
        {
            n1 = d2i(d);
        }
    [...]
    Ce que je n'aime pas trop dans ce genre de code de test, c'est qu'en convertissant toujours la même valeur dans une boucle, il me semble qu'un compilateur optimisant un minimum aggressivement peut très bien décider de générer du code équivalent à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    double d = -12345.1234665;
    int n1 = -12345;
    C'est pour cette raison que mon code est plus complexe afin de lui faire convertir plein de valeurs, et d'essayer de le perdre un peu. En fait, ce qui est difficile dans ce genre de tests, c'est qu'on veut que le compilateur soit hyper agressif dans son optimisation du code à tester, et hyper conservatif dans le code de test lui même...
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  3. #23
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 28
    Par défaut Quelques precisions
    Re-moi

    (Pardon pour les accents, je suis sur un Qwerty)

    J'ai retrouve mon code de test et l'ai reduit au maximum pour comparer uniquement ce qui nous interesse.

    En conclusion, la version assembleur et le d2i tournent a la meme vitesse a peu pres 3 fois plus vite que le cast.

    L'output est:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    double to int timings
    	3.078 -> using cast direct
    	1.500 -> using d2i fast
    	1.500 -> using asm direct
    	6.078 -> TOTAL
    Ce test est avec VC8 full-optim sur un dual-core a 2Ghz.
    Les mesures que j'ai faites auparavant etaient sur un Pentium 4 a 1.6Ghz, sur cette machine il y avait une difference de 10/20% entre d2i (un fadd plus un fstp) et le fistp et un rapport de 8 avec le cast (mais j'avais peut-etre active le modele floating point precis /fp:precise). Ce test est avec le modele fast (/fp:fast).

    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
    #define D2I_CONVERSION_FACTOR (1.5 * 4503599627370496.0)
    int _tmain(int argc, _TCHAR* argv[])
    {
    	const int iterations=500000000;
    	mylib::Timer timer;
    	volatile double theDouble=13.1;
    	volatile int theInt, guard1[4];
     
    	for (int i=0; i<iterations; i++)
    		theInt = static_cast<int>(theDouble);
    	timer.Step("using cast direct");
     
    	for (int i=0; i<iterations; i++)
    		*reinterpret_cast<volatile double *>(&theInt) =  theDouble + D2I_CONVERSION_FACTOR;
    	timer.Step("using d2i fast");
     
    	for (int i=0; i<iterations; i++) {
    		__asm {
    			fld qword ptr[theDouble]
    			fistp dword ptr[theInt]
    		}
    	}
    	timer.Step("using asm direct");
     
    	std::string report;
    	timer.Report("double to int timings", report);
    	std::cout << report;
    	return 0;
    }
    La boucle generee pour le cast est:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    		theInt = static_cast<int>(theDouble);
    00402121  fld         qword ptr [esp+14h] 
    00402125  call        _ftol2_sse (4099D0h) 
    0040212A  sub         esi,1 
    0040212D  mov         dword ptr [esp+1Ch],eax 
    00402131  jne         main+61h (402121h)
    Pour la version assembleur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    		__asm {
    			fld qword ptr[theDouble]
    			fistp dword ptr[theInt]
    		}
    004022A0  fld         qword ptr [esp+14h] 
    004022A4  fistp       dword ptr [esp+1Ch] 
    004022A8  sub         eax,1 
    004022AB  jne         main+1E0h (4022A0h)
    Pour la version d2i:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    		*reinterpret_cast<volatile double *>(&theInt) =  theDouble + D2I_CONVERSION_FACTOR;
    00402221  sub         eax,1 
    00402224  fld         qword ptr [esp+14h] 
    00402228  fadd        st,st(1) 
    0040222A  fstp        qword ptr [esp+1Ch] 
    0040222E  jne         main+161h (402221h)
    Pour finir, j'insiste sur le fait qu'avec le define que j'utilise, il n'y aura qu'une multiplication faite au moment de la COMPILATION. Il suffit de regarder le code genere par ton compilateur.

  4. #24
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 28
    Par défaut
    Citation Envoyé par JolyLoic
    Ce que je n'aime pas trop dans ce genre de code de test, c'est qu'en convertissant toujours la même valeur dans une boucle, il me semble qu'un compilateur optimisant un minimum aggressivement peut très bien décider de générer du code équivalent à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    double d = -12345.1234665;
    int n1 = -12345;
    C'est pour cette raison que mon code est plus complexe afin de lui faire convertir plein de valeurs, et d'essayer de le perdre un peu. En fait, ce qui est difficile dans ce genre de tests, c'est qu'on veut que le compilateur soit hyper agressif dans son optimisation du code à tester, et hyper conservatif dans le code de test lui même...
    Je suis d'accord, et c'est peut-etre ce qui se passe pour le code de test de thewho... i l faut regarder le code genere.
    Pour mon code, j'ai simplement specifie que les variables sont volatiles, ce qui garanti que l'optimisation ne peut rien sortir de la boucle.

  5. #25
    Membre émérite
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    633
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 633
    Par défaut
    Bonjour,
    Citation Envoyé par JolyLoic
    Ce que je n'aime pas trop dans ce genre de code de test, c'est qu'en convertissant toujours la même valeur dans une boucle, il me semble qu'un compilateur optimisant un minimum aggressivement peut très bien décider de générer du code équivalent à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    double d = -12345.1234665;
    int n1 = -12345;
    C'est pour cette raison que mon code est plus complexe afin de lui faire convertir plein de valeurs, et d'essayer de le perdre un peu. En fait, ce qui est difficile dans ce genre de tests, c'est qu'on veut que le compilateur soit hyper agressif dans son optimisation du code à tester, et hyper conservatif dans le code de test lui même...
    C'est un fait, mais avec pas mal de boucles, tu t'en aperçois immédiatement, et tu peux faire autre chose à ce moment là.

    Mais l'avantage, c'est qu'en dehors du temps nécessaire à la boucle elle-même, on mesure le temps effectivement nécessaire à la fonction (à peu près).

  6. #26
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Citation Envoyé par bricerive

    En conclusion, la version assembleur et le d2i tournent a la meme vitesse a peu pres 3 fois plus vite que le cast.

    L'output est:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    double to int timings
    	3.078 -> using cast direct
    	1.500 -> using d2i fast
    	1.500 -> using asm direct
    	6.078 -> TOTAL
    J'ai exécuté ton code sur ma machine, et j'ai comme valeurs :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    using cast direct : 2.812
    using d2i fast : 0.719
    using asm direct : 0.484
    En ajoutant le test de positivité pour faire une tronquation, d2i fast redevient plus long, avec environ 4s. Les résultats sont cohérents avec les miens, avec un écart plus marqué du fait qu'on fait moins d'opérations. Par contre, chez moi, la version assembleur est plus rapide.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  7. #27
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 28
    Par défaut
    Citation Envoyé par JolyLoic
    Les résultats sont cohérents avec les miens, avec un écart plus marqué du fait qu'on fait moins d'opérations. Par contre, chez moi, la version assembleur est plus rapide.
    Je pense que la comparaison assembleur contre d2i dépend enormément du CPU. D'où ces différences.

    En conclusion:
    -Si tu veux faire un cast (tronquer), utilise le cast - sauf si ton appli tourne en mode precis (/fp:precise) auquel cas d2i ira plus vite.
    -Si tu veux faire un round (arrrondi), utilise d2i (ou l'assembleur, mais c'est encore moins lisible et portable).

  8. #28
    Membre émérite
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    633
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 633
    Par défaut
    Bonjour,

    Bien entendu, ce qu'il faut utiliser dépend du programme.

    Il ne faut pas oublier que nous discutons certes d'un facteur de temps d'environ 2 à 3, mais sur une opération seulement, qui dans tous les cas reste rapide par rapport à d'autres.

    Même avec de très nombreux appels, il est probable que le reste du calcul soit largement prédominant pour le temps d'exécution.

Discussions similaires

  1. [MySQL] performance des jointures
    Par Bibicmoi dans le forum Langage SQL
    Réponses: 3
    Dernier message: 25/10/2006, 06h44
  2. Performances des langages
    Par Lunixinclar dans le forum Langages de programmation
    Réponses: 35
    Dernier message: 29/09/2006, 11h54
  3. Performance des Datasets
    Par Nafanga dans le forum Bases de données
    Réponses: 6
    Dernier message: 10/10/2005, 00h49
  4. performances des virtual functions
    Par xxiemeciel dans le forum C++
    Réponses: 2
    Dernier message: 25/07/2005, 17h24
  5. Performance des vertex array
    Par Mathieu.J dans le forum OpenGL
    Réponses: 13
    Dernier message: 25/06/2004, 10h47

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