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 :

[Optimisation]Est-ce possible ?


Sujet :

C++

  1. #1
    Membre éprouvé

    Inscrit en
    Juin 2004
    Messages
    1 397
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 1 397
    Par défaut [Optimisation]Est-ce possible ?
    Bonjour à tous !
    J'ai une fonction "inlinée" qui est énormément appelée, et je pense qu'elle est optimisable, mais je ne vois pas bien comment...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    __inline
    const Int gClip( const Int iX )
    {
      const Int i2 = (iX & 0xFF);
      if( i2 == iX )  { return iX; }
      if( iX < 0 )    { return 0x00; }
      else            { return 0xFF; }
    }
    Je pense en particulier à virer les if() mais je n'y parviens pas.
    Si jamais ça peut vous aider, le code est destiné à un ARMv5.
    Merci d'avance !

  2. #2
    Membre éprouvé Avatar de galak63
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    126
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 126
    Par défaut
    deja tu peux enlever le dernier "else" qui ne sert a rien, apres je vois pas

  3. #3
    Inactif  
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    743
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 743
    Par défaut
    Visiblement tu veux faire une saturation.

    2 pistes:

    -utiliser des instructions MMX/SSE2 qui savent faire ça automatiquement dans les calculs. Cette méthode n'est cependant pas évidente à mettre en oeuvre quand on n'a pas l'habitude du calcul vectoriel.

    -tu peux remplacer tes "if" par un min suivi d'un max. Mais plutôt que d'utiliser les min et max classiques (avec "if" ou "?:" qui doivent faire une fois sur deux un saut et donc cassent le pipeline du processeur), préfère les fonctions "__min" et "__max" sous Visual (ou leur équivalent pour d'autres compilos...)

  4. #4
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Quand ta fonction est inlinée le if devrait déjà être enlevé...
    Regarde le code généré par ton compilateur.

  5. #5
    Membre éprouvé

    Inscrit en
    Juin 2004
    Messages
    1 397
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 1 397
    Par défaut
    Justement, le code est assez fouillis, mais il contient plusieurs cmp, je pense donc que les if ne sont pas trop enlevés...

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 24
    Par défaut
    Bonjour,
    perso je ne vois pas de moyen d'optimiser encore la fonction, sauf en la codant en asm...

  7. #7
    Membre éprouvé

    Inscrit en
    Juin 2004
    Messages
    1 397
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 1 397
    Par défaut
    Merci pour les différents conseils .

  8. #8
    Membre expérimenté
    Inscrit en
    Décembre 2003
    Messages
    272
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 272
    Par défaut
    Tu peux éviter les sauts conditionnels au prix de quelques contorsions arithmétiques. Je ne suis ps sûr que le résultat soit plus rapide/efficace/court. De plus cela demande de bien savoir comment sont implémentés les Int (taille ? Où est le bit de signe ?).

    Le test (iX < 0) peut s'écrire (ix & 0x80000000), il suffit ensuite de convertir ce résultat en 0 ou 1. Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if( iX < 0 )    { return 0x00; }
      else            { return 0xFF; }
    devient
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    static Int tab[2] = { 0x00, 0xFF };
    return tab[(iX >> 31) & 1];
    Pour le test (iX & 0xFF) c'est plus délicat. Si tu es sûr qu'un réultat de test vaut 0 ou 1 (c'est le cas quand l'assembleur utilise des SETE/SETNE), tu peux utiliser (iX >> 8) && 1, ou bien (int)((bool)iX >> 8)) pour détecter des bits non nuls en dehors de ceux de poid faible. Ta fonction devient alors :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    __inline
    const Int gClip( const Int iX )
    {
        static Int tab[2] = { 0x00, 0xFF };
        Int local = (i >> 8) && 1;
        return (local * tab[(iX >> 31) & 1]) | (iX * (1-local));
    }
    Attention aux & et && !

  9. #9
    Membre éprouvé

    Inscrit en
    Juin 2004
    Messages
    1 397
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 1 397
    Par défaut
    C'est ce que je souhaitais faire...
    Maintenant, il va falloir que je regarde le code généré pour savoir si ça fonctionne, c'est bien cela ?

  10. #10
    Membre expérimenté
    Inscrit en
    Décembre 2003
    Messages
    272
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 272
    Par défaut
    ou juste vérifier que (27 && 1) vaut bien 1.

  11. #11
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Justement, le code est assez fouillis, mais il contient plusieurs cmp, je pense donc que les if ne sont pas trop enlevés...
    Avec O2 ?

  12. #12
    Inactif  
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    743
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 743
    Par défaut
    Citation Envoyé par loufoque
    Avec O2 ?
    Un compilateur ne peut pas supprimer les sauts conditionnels comme ça...

    Ici le plus simple sous Visual, et sans saut, c'est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    return __max(0,__min(255,x))
    Si t'as pas d'équivalent pour __min et __max avec ton compilo, il suffit de les programmer

  13. #13
    Membre expérimenté
    Inscrit en
    Décembre 2003
    Messages
    272
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 272
    Par défaut
    Citation Envoyé par loufoque
    Justement, le code est assez fouillis, mais il contient plusieurs cmp, je pense donc que les if ne sont pas trop enlevés...
    Ce ne sont pas les CMP qui gênent, mais les JGE/JLE et autres qui font les sauts. Un CMP couplé avec un SETE ne posera pas le problème de pipeline rompue, par exemple.

  14. #14
    Membre expérimenté
    Inscrit en
    Décembre 2003
    Messages
    272
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 272
    Par défaut
    Citation Envoyé par Charlemagne
    -tu peux remplacer tes "if" par un min suivi d'un max. Mais plutôt que d'utiliser les min et max classiques (avec "if" ou "?:" qui doivent faire une fois sur deux un saut et donc cassent le pipeline du processeur), préfère les fonctions "__min" et "__max" sous Visual (ou leur équivalent pour d'autres compilos...)
    En Visual C 2005, j'ai :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    #define __max(a,b)  (((a) > (b)) ? (a) : (b))
    #define __min(a,b)  (((a) < (b)) ? (a) : (b))
    :/

  15. #15
    Inactif  
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    743
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 743
    Par défaut
    Tiens oui, t'as raison. Je me suis trompé.
    J'étais convaincu du contraire, que min/max étaient implémentés différemment. J'avais pourtant eu (il me semble) des gains significatifs de vitesses grâce à __min/__max. Peut-être que dans certaines circonstances le compilo sait compiler l'opérateur "?:" sans saut.

    J'en reviens à MMX ou SSE2 qui proposent des calculs saturés, ainsi que des instructions min/max sans saut. C'est imbattable...

  16. #16
    Membre éprouvé

    Inscrit en
    Juin 2004
    Messages
    1 397
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 1 397
    Par défaut
    Le processeur est un ARM, que je connais assez mal.
    Comment écrire le min/max sans saut ?

  17. #17
    Inactif  
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    743
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 743
    Par défaut
    Par exemple

    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
    inline int max(int a, int b) 
    {
        b = a-b;
        a -= b & (b>>31);
        return a;
    }
    inline int min(int a, int b) 
    {
        b = b-a;
        a += b & (b>>31);
        return a;
    }
    inline int abs(int a) 
    {
        return a - ((a+a) & (a>>31));
    }
    PS: C'est peut-être pas si grâve que ça dans ton cas s'il y a des sauts, par exemple si tu sais que dans la grande majorité des cas tes valeurs sont comprises entre 0 et 255, tu peux t'arranger pour que les conditions des "if" soient remplies. Comme le processeur (en tout cas le x86) suppose que les conditions sont toujours remplies, le pipeline ne sera quasiment jamais brisé.

  18. #18
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Ca suppose quand même que les int sont codés sur 32 bits, et utilisent le premier bit pour coder le signe.

  19. #19
    Inactif  
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    743
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 743
    Par défaut
    Citation Envoyé par Laurent Gomila
    Ca suppose quand même que les int sont codés sur 32 bits, et utilisent le premier bit pour coder le signe.
    Ce n'était qu'un exemple fait à la va-vite pour montrer comment éviter les branchements.
    Plus on optimise plus on fait des suppositions sur le matériel.
    Les instructions MMX/SSE2 font aussi des suppositions, mais elles sont beaucoup plus rapides...

    Pour le problème du 32, on peut toujours utiliser 8*sizeof(int) à la place, mais là n'est pas le propos.

  20. #20
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Citation Envoyé par Charlemagne
    Un compilateur ne peut pas supprimer les sauts conditionnels comme ça...
    Bien sûr que si.
    Lorsqu'il fait de l'inlining il peut adapter la fonction en fonction de ses paramètres.

    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
    #include <cstdio>
     
    typedef int Int;
     
    inline const Int gClip( const Int iX )
    {
      const Int i2 = (iX & 0xFF);
      if( i2 == iX )  { return iX; }
      if( iX < 0 )    { return 0x00; }
      else            { return 0xFF; }
    }
     
    int main()
    {
        const int a = gClip(-1);
        std::printf("%d\n", a);
    }
    ne génère en fait chez moi que printf("%d\n", 0); (c'est particulièrement clair avec GCC/LLVM)

    C'est en fait bien souvent le plus simple qui est le plus performant. En ayant un code clair le compilateur est à même d'optimiser proprement.
    Le compilateur est d'ailleurs probablement plus malin que toi pour optimiser.

    Comme je l'ai déjà dit regarde ce que génère ton compilateur avant de dire que ce n'est pas optimisé...

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Est-il possible d'optimiser cette requête ?
    Par kraiggy dans le forum Développement
    Réponses: 6
    Dernier message: 20/03/2009, 15h49
  2. Réponses: 61
    Dernier message: 01/08/2008, 22h56
  3. Est-il possible d'optimiser cette requête ?
    Par Katachana dans le forum Requêtes
    Réponses: 2
    Dernier message: 25/06/2008, 14h50
  4. Réponses: 5
    Dernier message: 20/08/2006, 02h55
  5. Optimiser une requête..est-ce possible ?
    Par Thierry8 dans le forum Langage SQL
    Réponses: 9
    Dernier message: 27/09/2005, 11h31

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