c++ - ¿Los functores son realmente más rápidos que los punteros a las funciones?
function-pointers function-object (3)
Según Scott Meyers, un área donde C ++ brilla sobre C es que los objetos de función son más rápidos que los punteros de función. Él dice que esto se debe a que los objetos de función están en línea, lo que aumenta la velocidad.
Tengo dos preguntas sobre esto:
-
¿Cómo podemos verificar que los objetos de función estén, de hecho, en línea? ¿Podemos verificar esto en la práctica?
-
¿La alineación de los objetos de función depende del compilador que usamos, o todos los compiladores se comportan así?
- ¿Cómo podemos verificar que los objetos de función estén de hecho en línea? ¿Podemos verificar esto en la práctica?
Claro, inspeccione el código de ensamblador finalmente emitido.
- Los objetos de función de línea dependen del compilador que usamos, o ¿todos los compiladores se comportan así?
Depende en gran medida de la implementación del compilador y el nivel de optimización utilizado.
Entonces no, no hay garantía de que compiladores particulares (enlazadores) se comporten así.
Sin embargo, las llamadas a través de punteros de función no se pueden alinear.
Según él, los objetos de función están en línea, por lo que hay un aumento en la velocidad.
OMI "los objetos de función están en línea" deberían leerse mejor (o escucharse, no sé de dónde es esa cita):
los objetos de función pueden estar en línea mientras que las llamadas a través de punteros de función no.
Los estándares C ++ y C dejan mucha libertad a los compiladores. Los compiladores son libres de contar hasta mil millones entre cada instrucción, o solo lo hacen si un número entero tiene un valor primo.
Los compiladores "reales" decentes no hacen esto. Este es un problema de calidad de implementación.
Incluir objetos de función en algo como
std::sort
es algo que todo compilador real hace.
Es extremadamente fácil detectar lo que necesita ser insertado en esos casos, porque la información de tipo lleva consigo el código que necesita ser insertado.
Hacerlo con un puntero de función es más difícil.
Hacerlo con un puntero de función donde todo se ha convertido en punteros
void*
o
char*
es aún más difícil.
El efecto de esto es que, en la práctica, una llamada de estilo C a
qsort
frente a una llamada de estilo C ++ a
std::sort
puede resultar en una gran ventaja para
std::sort
.
qsort
es aproximadamente 2
qsort
más lento que
std::sort
, como se muestra
here
, en una situación ridículamente simple de ordenar enteros dispuestos aleatoriamente.
Inspeccionar la salida del código de ensamblaje real es principalmente un detalle, y es mucho trabajo por poco retorno. Tomar ejemplos concretos del mundo real te da una idea de cuán grande es realmente el impacto.
Los 3 de clang, gcc y MSVC fueron capaces de hacer que
std::sort
sea significativamente más rápido que su
qsort
.
Y como esta es una optimización fácil, mientras que optimizar los punteros de función en llamadas en línea no lo es, esperaría que los compiladores menos importantes no fueran mejores que esto en
qsort
.
Sí, los objetos de función pueden conducir a un código más rápido. Pero la única forma de garantizar eso es hacer una referencia.
-
La documentation dice: "Es posible que GCC aún no pueda alinear una función por muchas razones; la opción
-Winline
se puede usar para determinar si una función no se ha incorporado y por qué no " . -
Por supuesto, dependerá del compilador, la versión, los indicadores, etc. En ocasiones, la alineación puede ser contraproducente (expansión de código, etc.), por lo que cada compilador tiene su propio conjunto de reglas para decidir si una función debe estar incorporada. Por cierto, la palabra clave en
inline
es solo una pista, y algunas bibliotecas como eigen tienen dificultades para imponer la inline.