Je travaille sur un projet embarqué (seul compilateur C ++ 14 disponible) et je souhaite optimiser la vitesse d'exécution.

Voici un exemple de ce que je fais.

enum gpio_type{
  TYPE_1,
  TYPE_2
}

template <gpio_type T>
class test{
  test(){}

  void set_gpio(bool output)
  {
    switch (T)
    {
      case TYPE_1:
        do_something();
        break;

      case TYPE_2:
        do_something_else();
        break;
    }
  }
}

Le compilateur supprimera-t-il automatiquement le code mort au moment de la compilation? Si c'est le cas, est-ce une fonctionnalité standard ou dépend du compilateur? Si ce n'est pas le cas, est-il possible d'écrire le code d'une manière qui forcera l'optimisation?

5
Victor 7 mai 2020 à 10:41

4 réponses

Meilleure réponse

La propagation constante et l'élimination du code mort sont l'une des optimisations les plus simples du compilateur. Et comme T est une constante de temps de compilation, je serais extrêmement surpris si le code n'est optimisé par aucun compilateur.

J'ai testé 15 compilateurs et plates-formes sur godbolt du vénérable x86 à arm, avr, risc-v, framboise et arduino (et plus). Tous se compilent juste à l'équivalent d'un saut d'appel de queue. Pas de tests, pas de sauts conditionnels. Allez vérifier par vous-même.

À ce stade, je peux dire avec une certitude raisonnable qu'il n'y a aucune raison de modifier votre code en termes de performances.

3
bolov 7 mai 2020 à 10:05

Cela peut dépendre de l'activation ou non de l'optimisation et de l'intelligence de votre compilateur. Je suppose que les compilateurs actuels optimiseraient dans ce cas au moins s'ils incorporent la fonction.

Mais si vous voulez être sûr à 100%

  • spécialiser le modèle pour différentes valeurs d'énumération ou
  • utilisez votre commutateur et regardez la sortie assembleur de votre compilateur pour vérifier si le compilateur est optimisé comme vous le souhaitez ou
  • utiliser C ++ 17 et if constexpr
2
Werner Henze 7 mai 2020 à 07:52

Vous pouvez spécialiser set_gpio pour les différentes valeurs d'énumération - par exemple. :

template <gpio_type T>
class test{
  public:
    test(){}

    void set_gpio(bool output);
};

template<> void test<TYPE_1>::set_gpio(bool output) {
  do_something();
}

template<> void test<TYPE_2>::set_gpio(bool output) {
  do_something_else();
}

Comme d'autres réponses l'ont indiqué, vous n'aurez peut-être pas besoin de le faire si votre compilateur est proche de l'optimisation. Mais ce qui précède pourrait être plus lisible néanmoins.

3
Sander De Dycker 7 mai 2020 à 07:54

Je passerais le foncteur (do_something ou do_something_else) comme argument de modèle.

Ainsi, votre code de set_gpio devient plus clair et vous êtes sûr d'avoir une déduction au moment de la compilation de la fonction à prendre.

Dans cet article, vous pouvez voir comment cela se fait: Fonction transmise comme argument de modèle

0
schorsch312 7 mai 2020 à 07:47