Sé que en línea es una sugerencia o solicitud para el compilador y se usa para evitar gastos generales de llamadas a funciones.
Entonces, ¿sobre qué base se puede determinar si una función es candidata para alinearse o no? ¿En qué caso se debe evitar la inserción?
inline
es para el recién llegado de C ++ lo queCFLAGS
es para el recién llegado de Gentoo: no, compilar con-O3 -funroll-loops -finline-functions
no hará volar su antiguo Pentium;)Respuestas:
Evitar el costo de una llamada a funciones es solo la mitad de la historia.
hacer:
inline
lugar de#define
inline
: código más rápido y ejecutables más pequeños (más posibilidades de permanecer en el caché de código)no:
al desarrollar una biblioteca, para que una clase sea extensible en el futuro, debe:
Recuerde que la
inline
palabra clave es una pista para el compilador: el compilador puede decidir no incluir una función en línea y puede decidir incluir funciones que no se marcaroninline
en primer lugar. En general, evito marcar la funcióninline
(aparte, tal vez cuando escribo funciones muy muy pequeñas).En cuanto al rendimiento, el enfoque inteligente es (como siempre) perfilar la aplicación, y finalmente
inline
un conjunto de funciones que representan un cuello de botella.Referencias
EDITAR: Bjarne Stroustrup, El lenguaje de programación C ++:
EDIT2: ISO-IEC 14882-1998, 7.1.2 Especificadores de funciones
fuente
inline
es mucho más que una pista para el compilador. Cambia las reglas del lenguaje sobre múltiples definiciones. Además, tener datos estáticos no es una razón de hierro fundido para evitar incluir una función. La implementación está obligada a asignar un único objeto estático para cada función estática, ya sea que la función se declareinline
o no. Las clases siguen siendo extensibles si tienen constructores en línea y destructores virtuales. Y el destructor de llaves vacías es la única función virtual que a veces es una buena idea dejar en línea.inline
, el resultado es que la función no se alinea: usted paga el precio de la llamada y también cada unidad de traducción que incluye y llama a la función obtiene su propia copia del código y las variables estáticas. La razón para no incluir constructores y destructores cuando se desarrolla una biblioteca es la compatibilidad binaria con futuras versiones de su bibliotecainline
funciones pueden estar en línea si el compilador lo desea. Y lasinline
funciones no estarán alineadas si el compilador decide no incluirlas. Como dijo Charles Bailey, cambia las reglas del lenguaje. En lugar de pensar en ello como una pista de optimización, es más exacto considerarlo como un concepto completamente diferente. Lainline
palabra clave le dice al compilador que permita múltiples definiciones, y nada más. La optimización "en línea" se puede aplicar a casi cualquier función, esté o no marcadainline
.inline
para obtener la función en línea. A veces queremos los otros beneficios, como evitar ODR.inline
tiene muy poco que ver con la optimización.inline
es una instrucción para el compilador de no producir un error si la definición de la función dada ocurre varias veces en el programa y una promesa de que la definición se producirá en cada traducción que se use y en todas partes que aparezca tendrá exactamente la misma definición.Dadas las reglas anteriores,
inline
es adecuado para funciones cortas cuyo cuerpo no necesita incluir dependencias adicionales sobre lo que necesitaría una declaración. Cada vez que se encuentra la definición, se debe analizar y se puede generar código para su cuerpo, por lo que implica una sobrecarga del compilador sobre una función definida solo una vez en un solo archivo fuente.Un compilador puede en línea (es decir, reemplazar una llamada a la función con código que realiza esa acción de esa función) cualquier llamada de función que elija. Solía ser el caso de que "obviamente" no podía alinear una función que no se declaró en la misma unidad de traducción que la llamada, pero con el uso creciente de la optimización del tiempo de enlace, incluso esto no es cierto ahora. Igualmente cierto es el hecho de que las funciones marcadas
inline
pueden no estar en línea.fuente
inline
palabra clave? ¿Y qué es una feliz coincidencia?Decirle al compilador que alinee una función es una optimización, y la regla más importante de la optimización es que la optimización prematura es la raíz de todo mal. Siempre escriba código claro (usando algoritmos eficientes), luego perfile su programa y solo optimice las funciones que están tardando demasiado.
Si encuentra que una función en particular es muy corta y simple, y se llama decenas de miles de veces en un circuito interno cerrado, podría ser un buen candidato.
Sin embargo, es posible que se sorprenda: muchos compiladores de C ++ incorporarán automáticamente pequeñas funciones para usted, e incluso podrían ignorar su solicitud.
fuente
/FAcs
en Visual Studio,-s
en GCC) para ver exactamente lo que hace. En mi experiencia, ambos compiladores sopesan bastante la palabra clave en línea.inline
palabra clave en absoluto. Es decir, si ve que la función está en línea y elimina elinline
especificador, seguirá estando en línea. Si tienes ejemplos específicos de lo contrario, ¡compártelos!inline
obstaculiza la palabra clave "código claro"? La palabra clave en "optimización prematura" es prematura , no optimización. Decir que debes * evitar activamente las optimizaciones es solo basura. El punto de esa cita es que debe evitar las optimizaciones que pueden no ser necesarias y tener efectos secundarios dañinos en el código (como hacerlo menos mantenible). No veo cómo lainline
palabra clave hará que el código sea menos mantenible, o cómo puede ser perjudicial agregarlo a una función.La mejor manera de averiguarlo es crear un perfil de su programa y marcar pequeñas funciones que se llaman muchas veces y grabar ciclos de CPU de esa manera
inline
. La palabra clave aquí es "pequeña": una vez que la sobrecarga de la llamada de función es insignificante en comparación con el tiempo dedicado a la función, no tiene sentido alinearlos.El otro uso que sugeriría es que si tiene funciones pequeñas que se llaman en el código crítico de rendimiento con la frecuencia suficiente para hacer que una memoria caché pierda relevancia, probablemente también debería incluirlas. De nuevo, es algo que el perfilador debería poder decirte.
fuente
¡La optimización temprana es la raíz de todo mal!
Como regla general, generalmente solo incluyo "getters" y "setters". Una vez que el código funciona y es estable, la creación de perfiles puede mostrar qué funciones podrían beneficiarse de la incorporación.
Por otro lado, la mayoría de los compiladores modernos tienen algoritmos de optimización bastante buenos, y alinearán lo que debería haber alineado para usted.
Reasumir: escriba funciones de línea única y se preocupe por las demás más adelante.
fuente
Las funciones en línea pueden mejorar el rendimiento de su código al eliminar la necesidad de insertar argumentos en la pila. si la función en cuestión está en una parte crítica de su código, debe tomar la decisión en línea, no en línea, en la parte de optimización de su proyecto,
puedes leer más sobre las líneas en las preguntas frecuentes de c ++
fuente
A menudo uso las funciones en línea no como una optimización, sino para hacer que el código sea más legible. A veces, el código en sí es más corto y más fácil de entender que los comentarios, los nombres descriptivos, etc. Por ejemplo:
El lector conoce de inmediato la semántica completa del código.
fuente
Generalmente sigo una regla de pulgar donde hago una función con 3-4 declaraciones simples como en línea. Pero es bueno recordar que es solo una pista para el compilador. La última llamada para que esté en línea o no la toma el compilador únicamente. Si hay más de estas muchas declaraciones, no declararé en línea, ya que con un compilador estúpido, puede provocar una acumulación de código.
fuente
La mejor manera sería examinar y comparar las instrucciones generadas para en línea y no en línea. Sin embargo, siempre es seguro omitirlo
inline
. Usarinline
podría generar problemas que no quieres.fuente
Cuando decido si usar en línea, generalmente tengo en cuenta la siguiente idea: en las máquinas modernas, la latencia de memoria puede ser un cuello de botella más grande que los cálculos en bruto. Se sabe que las funciones de línea que se llaman a menudo aumentan el tamaño del ejecutable. Además, dicha función podría almacenarse en el caché de código de la CPU, lo que disminuirá el número de errores de caché cuando se necesite acceder a ese código.
Por lo tanto, tiene que decidir por usted mismo: ¿la alineación aumenta o disminuye el tamaño del código máquina generado? ¿Qué tan probable es que llamar a la función cause una pérdida de caché? Si está salpicado en todo el código, entonces diría que la probabilidad es alta. Si está restringido a un solo ciclo cerrado, entonces la probabilidad es baja.
Normalmente uso inlining en los casos que enumero a continuación. Sin embargo, cuando está realmente preocupado por el rendimiento, la creación de perfiles es esencial. Además, es posible que desee comprobar si el compilador realmente toma la pista.
fuente
Además, un método en línea tiene graves efectos secundarios al mantener proyectos grandes. Cuando se cambia el código en línea, el compilador reconstruirá automáticamente todos los archivos que lo utilizan (es un buen compilador). Esto podría desperdiciar mucho tiempo de desarrollo.
Cuando un
inline
método se transfiere a un archivo fuente y ya no está en línea, se debe reconstruir todo el proyecto (al menos esta ha sido mi experiencia). Y también cuando los métodos se convierten en línea.fuente
inline
o no, no tiene importancia (que no sea sin lainline
palabra clave, obtendrá errores de enlace - pero lainline
palabra clave no es el problema que causa reconstrucciones excesivas.Uno debería usar el calificador de función en línea solo cuando el código de la función es pequeño. Si las funciones son más grandes, debería preferir las funciones normales ya que el ahorro en espacio de memoria vale el sacrificio comparativamente pequeño en la velocidad de ejecución.
fuente
Cuando piense que su código es lo suficientemente pequeño como para usarlo en línea y recuerde que la función en línea duplica su código y péguelo donde se llama la función, por lo que puede ser lo suficientemente bueno como para aumentar su tiempo de ejecución pero también un mayor consumo de memoria. No puede usar la función en línea cuando está usando un bucle / variable estática / recursiva / switch / goto / función virtual. Virtual significa esperar hasta el tiempo de ejecución e inline significa durante la compilación para que no puedan usarse simultáneamente.
fuente
He leído algunas respuestas y veo que faltan algunas cosas.
La regla que uso es no usar en línea, a menos que quiera que esté en línea. Parece tonto, ahora explicación.
Los compiladores son lo suficientemente inteligentes y las funciones cortas siempre están en línea. Y nunca hace una función larga como en línea, a menos que el programador diga que lo haga.
En realidad
inline
es un pedido para el compilador, no tiene opciones y después de que lainline
palabra clave hace que todo el código esté en línea. Por lo tanto, nunca puede usarinline
palabras clave y el compilador diseñará el código más corto.Entonces, ¿cuándo usarlo
inline
?Para usar si quieres tener algún código en línea. Solo conozco un ejemplo, porque lo uso en una sola situación. Es autenticación de usuario.
Por ejemplo tengo esta función:
No importa cuán grande sea esta función, quiero tenerla en línea porque hace que mi software sea más difícil de descifrar.
fuente