Dans son livre, The C++ Standard Library (Second Edition)
Nicolai Josuttis déclare que les lambdas peuvent être mieux optimisées par le compilateur que les fonctions simples.
De plus, les compilateurs C ++ optimisent les lambdas mieux que les fonctions ordinaires. (Page 213)
Pourquoi donc?
Je pensais qu'en matière d'inlining, il ne devrait plus y avoir de différence. La seule raison à laquelle je pourrais penser est que les compilateurs pourraient avoir un meilleur contexte local avec les lambdas et que ceux-ci peuvent faire plus d'hypothèses et effectuer plus d'optimisations.
c++
optimization
c++11
lambda
compiler-optimization
Stéphan Dollberg
la source
la source
Réponses:
La raison en est que les lambdas sont des objets de fonction, donc les transmettre à un modèle de fonction instanciera une nouvelle fonction spécifiquement pour cet objet. Le compilateur peut ainsi intégrer de manière triviale l'appel lambda.
Pour les fonctions, en revanche, l'ancienne mise en garde s'applique: un pointeur de fonction est passé au modèle de fonction, et les compilateurs ont traditionnellement beaucoup de problèmes pour insérer des appels via des pointeurs de fonction. Ils peuvent théoriquement être insérés, mais uniquement si la fonction environnante est également incorporée.
À titre d'exemple, considérons le modèle de fonction suivant:
Appelez-le avec un lambda comme ceci:
Résultats dans cette instanciation (créée par le compilateur):
… Le compilateur sait
_some_lambda_type::operator ()
et peut les appeler en ligne de manière triviale. (Et appeler la fonctionmap
avec n'importe quel autre lambda créerait une nouvelle instanciation demap
puisque chaque lambda a un type distinct.)Mais lorsqu'elle est appelée avec un pointeur de fonction, l'instanciation se présente comme suit:
… Et
f
pointe ici vers une adresse différente pour chaque appel àmap
et donc le compilateur ne peut pas appeler en ligne àf
moins que l'appel environnant àmap
n'ait également été inséré afin que le compilateur puisse résoudref
une fonction spécifique.la source
std::sort
est l'exemple classique de ceci en utilisant des lambdas au lieu d'un pointeur de fonction ici apporte jusqu'à sept fois (probablement plus, mais je n'ai pas de données à ce sujet!) les performances augmentent.std::sort
, oumap
dans mon exemple) et le lambda lui - même. Le lambda est généralement petit. L'autre fonction - pas nécessairement. Nous sommes concernés par les appels en ligne au lambda à l'intérieur de l'autre fonction.pred
dont la définition est visible, et en utilisant gcc v5.3,std::find_if(b, e, pred)
ne se met pas en lignepred
, mais lestd::find_if(b, e, [](int x){return pred(x);})
fait. Clang parvient à intégrer les deux, mais ne produit pas de code aussi vite que g ++ avec le lambda.Parce que lorsque vous passez une "fonction" à un algorithme, vous passez en fait un pointeur vers la fonction, il doit donc faire un appel indirect via le pointeur vers la fonction. Lorsque vous utilisez un lambda, vous passez un objet à une instance de modèle spécialement instanciée pour ce type et l'appel à la fonction lambda est un appel direct, pas un appel via un pointeur de fonction, il est donc beaucoup plus probable qu'il soit en ligne.
la source