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 :

Mutualisation de code template et non template


Sujet :

C++

  1. #1
    Membre confirmé
    Avatar de Captain'Flam
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2011
    Messages
    273
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Février 2011
    Messages : 273
    Points : 455
    Points
    455
    Billets dans le blog
    1
    Par défaut Mutualisation de code template et non template
    Bonjour à toutes et tous,

    je me pose une question existentielle sur la meilleure façon de mutualiser le code d'un algo selon qu'il soit "templetisé" ou non.

    J'ai une fonction qui code un algo assez compliqué et consommateur de CPU.
    Il peut être bien optimisé par le compilateur si certains de ses paramètres sont des puissances de 2 connues à l'avance.
    Or, dans 99% des cas, les paramètres en question sont justement des puissances de 2 connues à l'avance.
    J'ai donc une implémentation sous forme template qui permet au compilateur d'optimiser un max.
    Et une version "générique" avec des paramètres quelconques, pour les rares cas où les paramètres n'ont pas des valeurs "classiques".

    Voici un exemple (ou mon algo compliqué a été remplacé par une simple division) :

    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
     
    template<int N> int algo_template ( int x )
        {
        return x/N ; // ici un algo super compliqué que le compilateur peut optimiser si N est une puissance de 2 constante
        }
     
    int algo_non_template ( int x , int N )
        {
        return x/N ; // le même algo qui ne sera pas optimisé par le compilateur (mais qui sert rarement)
        }
     
    int algo ( int x , int n ) // on sait que n vaut très souvent 16 ou 32
        {
        switch ( n )
            {
            case 16 : return algo_template<16>( x ) ;
            case 32 : return algo_template<32>( x ) ;
            default : return algo_non_template( x,n ) ; // ne se produit que très rarement
            }
        }
    Ma question :
    Y a-t-il un moyen élégant et cplusplussien de n'avoir qu'un seul exemplaire du code de l'algo (qui est beaucoup plus gros que l'exemple en une ligne donné ici) ?

    Merci d'avance !
    Captain'Flam
    anciennement Sopsag, aka Hadrien
    Win seven x64 & Win 10 / Visual 2017 / Python 2.7 / Eclipse

  2. #2
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    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 189
    Points : 17 141
    Points
    17 141
    Par défaut
    En gros, si tu veux choisir une fonction selon un paramètre connu uniquement à l'exécution (at runtime), tu ne peux pas faire vraiment mieux que ca.

    Si tu arrivais à faire en sorte d'avoir ton N fixé à la compilation, ca serait une autre histoire.
    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
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Template sont définis à la compilation et non à l'exécution, donc dans l'absolu non. Tu dois écrire la fonction template, et la fonction "normale".
    Par contre, tu peux n'avoir envie d'écrire qu'un seul code s'ils sont vraiment identiques. Et pour ça, le préprocesseur et les define sont là pour le dupliquer correctement à ta place.
    Tu peux écrire tout le corps de la fonction dans un fichier, mettons algo_body.h et écrire quelque chose comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    template<int N> void algo(int x) {
    #include "algo_body.h"
    }
    void algo(int x, int N) {
    #include "algo_body.h"
    }
    Mais ça sera ta seule option possible je pense. Ca permet déjà d'éviter les erreurs copier/coller ou oubli de fix d'un côté ou l'autre
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  4. #4
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    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 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Surtout, n'utilise pas l'extension .h. Choisis n'importe quoi d'autre, comme .macro ou .bazar.
    le fichier en question n'est pas un en-tête légitime.
    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

  5. #5
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Points : 1 878
    Points
    1 878
    Billets dans le blog
    21
    Par défaut
    Tout dépend de la façon dont fonctionne l'optimisation dans ton compilateur. C'est connu pour être un des domaines les plus pointus, maîtrisés par le moins de personnes.

    Dans l'ensemble on pourrait imaginer qu'avec:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int algo_non_template(int i, int n) { return i / n; }
    template <int N> int algo_template(int i) { return algo_non_template(i, N); }
    l'optimiseur puisse tenir compte du fait que N est connu à la compilation dans le deuxième cas. Je ne sais même pas s'il y a de la doc sur le sujet.

    Cela étant dit, je suppose que la caractéristique intéressante des puissances de deux se révèle dans certaines parties de l'algorithme seulement. Mettons que cela soit de pouvoir multiplier / diviser par décalage de x bits plutôt que de passer par les opérations généralistes de multiplication et de division.

    Dans ces cas-là, il reste une possibilité plus élégante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    template <typename Div>
    int mon_algo(int i, int n, Div&& div) {
      return div(i, n);
    }
     
    ...
     
    switch (n) {
      case 32: return mon_algo(i, n, [](int a, int b) { return a >> 5; } );
      ...
      default: return mon_algo(i, n, [](int a, int b) { return a / b;} );
    }

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

    Informations professionnelles :
    Activité : aucun

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

    En fait, je me pose une première question... : Quand tu dis
    Et une version "générique" avec des paramètres quelconques, pour les rares cas où les paramètres n'ont pas des valeurs "classiques".
    S'agit-il d'avoir des valeurs (puissance de 2) qui ne seront connues qu'à l'exécution, ou d'avoir des valeurs connues à la compilation mais qui ne sont pas des puissances de 2 (ou pire : avoir des valeurs connues uniquement à l'exécution qui ne sont pas **forcément** des puissances de deux)

    Car, si les valeurs sont connues à la compilation, il est ** peut-être ** possible de "simplement" fournir une spécialisation différente (en fait, d'utiliser l'absence de spécialisation) pour que cela fonctionne.

    Il peut, en effet, être assez facile de déterminer si une valeur connue à la compilation est une puissance de 2 sous une forme template, et donc de déterminer l'algorithme à utiliser à la compilation. Par contre, si la valeur n'est connue qu'à l'exécution, les template ne te seront d'aucune utilité
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  7. #7
    Membre confirmé
    Avatar de gb_68
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2006
    Messages
    232
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2006
    Messages : 232
    Points : 546
    Points
    546
    Par défaut
    En utilisant std::integral_constant (ou une classe équivalente si pas de c++11 ), cela devrait permettre au compilateur de correctement propager les constantes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    template<typename Integer> int algo_impl(int x, Integer N) // algo trop volumineux pour propager une constante simplement par inlining
    {
        return x/N;
    }
     
    int algo(int x , int n) // on sait que n vaut très souvent 16 ou 32
    {
        switch(n)
        {
            case 16 : return algo_impl(x, std::integral_constant<int, 16>()) ;
            case 32 : return algo_impl(x, std::integral_constant<int, 32>()) ;
            default : return algo_impl(x, n) ; // ne se produit que très rarement
        }
    }

Discussions similaires

  1. Réponses: 2
    Dernier message: 15/09/2014, 11h51
  2. Réponses: 3
    Dernier message: 09/04/2009, 11h30
  3. Réponses: 8
    Dernier message: 20/07/2007, 14h28
  4. Méthode template dans classe non template ?
    Par shenron666 dans le forum Langage
    Réponses: 12
    Dernier message: 04/09/2006, 17h50
  5. code incomprehensible (3 lignes) : template, typename
    Par xavlours dans le forum Langage
    Réponses: 7
    Dernier message: 25/02/2005, 14h45

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