2011-01-31 7 views
6

Los compiladores C/C++ optimizan las funciones de capa única con parámetros constantes (conocidas en tiempo de compilación) solo cuando se usan -Os, -O1 y -O2. No optimizan todas las capas. Solo -O3 puede hacer eso. gcc es WinAVR 4.3.3 que no admite el atributo "optimizar".c/C++ optimizar para variable constante en las funciones de llamada

void inner(double value) 
{ 
    //operations using value 
    //... 
} 

void outer(double value) 
{ 
    //few operations using value 
    //... 
    inner(value); 
} 

int main() 
{ 
    inner(1); //optimize 
    outer(1); //only optimize by using -O3 
} 

¿Cuáles son las posibles soluciones aparte de las siguientes?

  1. -O3 programa de retención o archivo (mal uso va a explotar el tamaño)
  2. atribuyen optimizar -O3 para las funciones (4.3.3 no soporta)
  3. macro (propenso a errores)

actualización:

//inner function 
static inline void _delay_us(double __us) __attribute__((always_inline)); 
//outer function 
void f(double); 
inline f1(double); 
static inline f2(double); 
static f3(double); 

f1 está optimizado b ut give warning '_delay_us' es estático pero se usa en la función en línea 'f1' que no es estática debido al problema de la función estática. Otros no están optimizados.


Solución:

static inline void outer(double) __attribute__((always_inline)); 

en línea es la clave. Mi función externa es demasiado grande para en línea. El atributo always_inline obliga a la función a estar en línea. Esto permite que el compilador optimice la función con un costo de compilación menor que tratando de descubrir la optimización. -O3 es lo suficientemente inteligente como para hacer la optimización pero no -Os. -Es posible que necesite algunas opciones de compilación. (La palabra clave estática es necesaria porque la función interna también está estática en línea.)

+0

Hm, no estoy seguro de entender por qué esto es una preocupación. Si quieres que el compilador optimice, díselo. Si teme que '-O3' (o cualquier nivel) explote el tamaño del código,' -Os' es el camino a seguir. –

+0

El código se usa en microcontroladores de 8 bits que no tienen hardware de coma flotante ALU. -O3 de hecho da un tamaño de código más pequeño que -Os en esta función, 4k vs 400 – keithyip

Respuesta

3

Algo similar a la opción de macro (3), pero sin las desventajas de una macro, puede realizar funciones específicas inline, que típicamente darán como resultado las optimizaciones constantes deseadas. Por supuesto, esto solo ayuda si está llamando a las funciones relevantes desde un solo lugar (o desde algunos lugares), de lo contrario, la hinchazón del código se convierte en un problema.

Tenga en cuenta que gcc tiene una disposición para obligar a las funciones en línea específicas a estar siempre en línea (en lugar de dejar esto a discreción del compilador): __attribute__ ((always_inline)). Otros compiladores generalmente tendrán un mecanismo similar, aunque puede ser un cambio de línea de comando o un pragma.

+0

Tenga en cuenta que (estándar C++) 'inline' es solo una pista para el compilador. El compilador puede ignorar tales sugerencias si el compilador determina que la línea no vale la pena o no es necesaria. Cómo se toma esta decisión depende de la implementación. –

+0

@In silico: cierto, pero gcc le permite forzar las funciones en línea para que estén en línea: '__atttribute__ ((always_inline))' –

+0

¡Fallé al intentar en línea! Actualicé la publicación. – keithyip

1

En GCC al menos, las banderas -O solo activan una carga completa de otras banderas, consulte p. Ej. http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html. Simplemente puede habilitar las que le interesan, aunque eso generalmente se desaconseja.

Tenga en cuenta que no estoy seguro de que el comportamiento de, p. GCC en -O2 y -O3 es necesariamente un indicador de lo que hará un compilador completamente diferente.

+0

Las opciones individuales son muy útiles en la programación de microcontroladores. – keithyip

+0

@nothing: De hecho, a pesar de que a menudo te lleva a la ingeniería en una esquina, en mi experiencia! –

0

Como un punto general, si aumenta la información que proporciona al compilador, entonces podría ser capaz de realizar una mejor optimización.

Por ejemplo, suponiendo que esas son las únicas llamadas a inner y outer entonces se podría declarar como static para limitar su alcance y permitir que el compilador de una mayor flexibilidad en la forma en que los optimiza.

En función del contenido real de las funciones que podría también puede declarar sus parámetros como const que permite que el compilador sabe de inmediato que no se pueden cambiar sin que tener que analizar el código

static void inner(const double value) 
{ 
    //operations using value 
} 

static void outer(const double value) 
{ 
    //few operations using value 
    //... 
    inner(value); 
} 
+0

const parameters no ayuda mucho. Mi función externa es demasiado costosa en tiempo de compilación para optimizar automáticamente sin forzar en línea. – keithyip

0

¿Qué hay de la introducción de una función 'outerFast', definida en su propia cpp, incluyendo las definiciones de inner y outer, y compilando solo ese archivo con -O3?

Tiene sus propias desventajas, sin embargo.

+0

Estoy escribiendo algunas bibliotecas. La configuración compleja no es fácil de usar para los usuarios, pero el fino control de optimización para archivos individuales es muy útil en la producción. – keithyip

Cuestiones relacionadas