Question

Profilage mon code C ++ avec gprof, j'ai découvert qu'une partie importante de mon temps est consacré à appeler une méthode virtuelle et encore. La méthode elle-même est court et pourrait probablement être inline si ce ne virtuel.

Quels sont les moyens que je pourrais accélérer ce peu de réécriture tout pour ne pas être virtuel?

Était-ce utile?

La solution

Il est parfois instructif d'examiner comment vous écrire le code dans le bon vieux « C » si vous n'avez pas de sucre syntaxique de C ++ disponible. Parfois, la réponse n'utilise un appel indirect. Voir cette réponse pour un exemple.

Autres conseils

Êtes-vous sûr que le temps est tout associé à un appel? Serait-ce la fonction elle-même où le coût est? Si tel est le cas simplement inline les choses pourraient faire fonctionner votre profileur de disparaître, mais vous ne verrez pas beaucoup de vitesse vers le haut.

Si l'on suppose qu'il est vraiment la surcharge de faire tant d'appels virtuels, il y a une limite à ce que vous pouvez faire sans faire des choses non virtuel.

Si l'appel a early-out pour des choses comme le temps / drapeaux alors je vais souvent utiliser une approche à deux niveaux. La vérification est inline avec un appel non virtuel, le comportement spécifique à la classe appelée seulement si nécessaire.

par exemple.

class Foo
{
public:

inline void update( void )
{
  if (can_early_out)
    return;

  updateImpl();
}

protected:

virtual void updateImpl( void ) = 0;    
}; 

Si l'appel virtuel est vraiment le goulot d'étranglement donner CRTP essayer.

est le moment passé dans l'appel de fonction réelle, ou dans la fonction elle-même?

Un appel de fonction virtuelle est sensiblement plus lent qu'un appel non virtuel, parce que l'appel virtuel nécessite un déréférencement supplémentaire. (Google pour 'vtable' si vous voulez lire tous les détails poilus.)) Mise à jour: Il se le Wikipedia article est pas mal à ce sujet.

ici « Sensiblement », cependant, signifie deux instructions Si cela consomme une partie importante du calcul total, y compris le temps passé dans la fonction appelée, qui sonne comme un endroit merveilleux pour envisager unvirtualizing et inline.

Mais quelque chose près de 20 ans de C ++, je ne pense pas que j'ai jamais vu que vraiment arriver. J'aimerais voir le code.

S'il vous plaît être conscient que « virtuel » et « en ligne » ne sont pas opposés - une méthode peut être à la fois. Le compilateur se fera un plaisir inline une fonction virtuelle si elle peut déterminer le moment à la compilation type de l'objet:

struct B {
    virtual int f() { return 42; }
};

struct D : public B {
    virtual int f() { return 43; }
};

int main(int argc, char **argv) {
    B b;
    cout << b.f() << endl;   // This call will be inlined

    D d;
    cout << d.f() << endl;   // This call will be inlined

    B& rb = rand() ? b : d;
    cout << rb.f() << endl;  // Must use virtual dispatch (i.e. NOT inlined)
    return 0;
}

[MISE À JOUR: Fait certain type d'objet véritable dynamique de rb ne peut pas être connu au moment de la compilation - grâce à MSalters]

Si le type de l'objet peut être déterminée au moment de la compilation, mais la fonction n'est pas inlineable (par exemple, il est grand ou est définie en dehors de la définition de la classe), elle sera appelée non virtuellement.

Vous pourriez être en mesure obtenir un peu de meilleures performances de l'appel virtuel en changeant la convention d'appel. Le vieux compilateur Borland avait une convention __fastcall qui a passé des arguments dans les registres cpu au lieu de la pile.

Si vous êtes coincé avec l'appel virtuel et les quelques opérations comptent vraiment, puis vérifier la documentation de votre compilateur pour les conventions d'appel pris en charge.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top