En su libro, The C++ Standard Library (Second Edition)
Nicolai Josuttis afirma que el compilador puede optimizar mejor las lambdas que las funciones simples.
Además, los compiladores de C ++ optimizan las lambdas mejor que las funciones normales. (Página 213)
¿Porqué es eso?
Pensé que cuando se trata de alinear ya no debería haber ninguna diferencia. La única razón por la que podría pensar es que los compiladores pueden tener un mejor contexto local con lambdas y eso puede hacer más suposiciones y realizar más optimizaciones.
c++
optimization
c++11
lambda
compiler-optimization
Stephan Dollberg
fuente
fuente
Respuestas:
La razón es que las lambdas son objetos de función, por lo que pasarlas a una plantilla de función creará una nueva función específicamente para ese objeto. De este modo, el compilador puede en línea trivialmente la llamada lambda.
Para las funciones, por otro lado, se aplica la advertencia anterior: se pasa un puntero de función a la plantilla de función, y los compiladores tradicionalmente tienen muchos problemas para alinear llamadas a través de punteros de función. Teóricamente pueden estar en línea, pero solo si la función circundante también está en línea.
Como ejemplo, considere la siguiente plantilla de función:
Llamándolo con una lambda como esta:
Resultados en esta instanciación (creada por el compilador):
... el compilador sabe
_some_lambda_type::operator ()
y puede hacer llamadas en línea de manera trivial. (E invocar la funciónmap
con cualquier otra lambda crearía una nueva instancia demap
ya que cada lambda tiene un tipo distinto).Pero cuando se llama con un puntero de función, la instanciación se ve de la siguiente manera:
… Y aquí
f
apunta a una dirección diferente para cada llamadamap
y, por lo tanto, el compilador no puede hacer llamadas en línea af
menos que la llamada amap
también se haya en línea para que el compilador pueda resolverf
una función específica.fuente
std::sort
Es el ejemplo clásico de esto usando lambdas en lugar de un puntero de función que aquí trae hasta siete veces (¡probablemente más, pero no tengo datos sobre eso!) El rendimiento aumenta.std::sort
, omap
en mi ejemplo) y la propia lambda. La lambda suele ser pequeña. La otra función, no necesariamente. Nos interesan las llamadas en línea a la lambda dentro de la otra función.pred
cuya definición es visible, y usar gcc v5.3,std::find_if(b, e, pred)
no está en líneapred
, perostd::find_if(b, e, [](int x){return pred(x);})
sí. Clang logra alinear ambos, pero no produce código tan rápido como g ++ con el lambda.Porque cuando pasa una "función" a un algoritmo, de hecho, está pasando un puntero para que funcione, por lo que tiene que hacer una llamada indirecta a la función a través del puntero. Cuando usa una lambda, está pasando un objeto a una instancia de plantilla especialmente instanciada para ese tipo y la llamada a la función lambda es una llamada directa, no una llamada a través de un puntero de función, por lo que es mucho más probable que esté en línea.
fuente