2010-01-07 13 views
14

que tienen una función que opera en el pedazo de datos (digamos, un int), y quiero cambiarlo en lugar de pasar por una referencia a la valule. Como tal, tengo la función: void myFunction(int *thing) { ... }. Cuando lo uso lo llamo así: myFunction(&anInt).¿GCC alineará una función que toma un puntero?

Como mi función se llama con frecuencia (pero de muchos lugares diferentes) Estoy preocupado por su rendimiento. La razón por la que lo he refactorizado en una función es la capacidad de prueba y la reutilización del código.

¿El compilador podrá optimizar la función, alineándola para operar directamente en mi variable anInt?

Espero que responda esta pregunta con el espíritu que se le pide (es decir, no estoy preocupándome prematuramente por la optimización, tengo curiosidad por la respuesta). Del mismo modo, no quiero convertirlo en una macro.

Respuesta

9

GCC es bastante inteligente. Considere este fragmento de código:

#include <stdio.h> 

void __inline__ inc(int *val) 
{ 
    ++ *val; 
} 

int main() 
{ 
    int val; 

    scanf("%d", &val); 

    inc(&val); 

    printf("%d\n", val); 

    return 0; 
} 

Después de un gcc -S -O3 test.c que obtendrá el siguiente asm relevante:

... 
call __isoc99_scanf 
movl 12(%rsp), %esi 
movl $.LC1, %edi 
xorl %eax, %eax 
addl $1, %esi 
movl %esi, 12(%rsp) 
call printf 
... 

Como se puede ver, no hay necesidad de ser un experto asm para ver el inc() la llamada se ha convertido en una instrucción de incremento.

+0

¡Al menos con GCC 4.4.2, ni siquiera necesita ser marcado como 'en línea'! (Aunque el uso de 'static' evitará una copia adicional de la función en el binario generado.) – ephemient

6

Hay dos cuestiones aquí - se puede optimizar el código, y sin él. Ciertamente puede ser, pero la "voluntad" depende del estado de ánimo en que se encuentre el optimizador. Si esto es realmente importante para usted, compile el código y eche un vistazo al resultado del lenguaje ensamblador.

Además, parece que está combinando dos problemas. Una función en línea efectivamente tiene su cuerpo pegado en el sitio de llamada. Si está usando punteros o no, no está ni aquí ni allá. Pero usted parece estar preguntando si el compilador puede transformar:

int x = 42; 
int * p = & x; 
* p = * p + 1; 

en

x = x + 1; 

Esto es mucho más difícil que el optimizador para ver.

+0

¡No estoy en la etapa en la que estoy listo para leer la salida de ensamblaje! – Joe

+0

Busque su edición más reciente con 'x' y' p': sí, esa es exactamente la pregunta que estoy haciendo. Sé que es difícil, es por eso que estaba preguntando si era posible o no. – Joe

+0

Como dije, es posible. ¿GCC lo hago? No lo sé. –

-1

¿Qué versión de compilador estás usando? ¿Con qué opciones? ¿En qué plataforma?

Todas estas preguntas tienen la respuesta. Realmente necesita compilar el código y mirar el conjunto para estar seguro.

1

Lo hará (o al menos puede). Hay algunas razones por las que la función no puede incluirse en línea, p. Ej. cuando intenta acceder a un puntero de la función (llamando a la función por referencia, está accediendo a los parámetros por referencia, lo que está bien). Puede haber otra situación

intentaremos declarar la función con "línea extern" (variables estáticas seguro?) - esto evita que el compilador emita el organismo autónomo. Si no puede alinear la función, emitirá un error.

+0

C99 dice que 'extern inline' hace que se genere código de objeto independiente, y GCC seguirá estas reglas extrañas si se pone en modo C99. De lo contrario, el comportamiento predeterminado de GCC es lo que has indicado. (C89 no dice nada, y podría decirse que son mejores semánticas.) – ephemient

2

No debería importar si el argumento es un puntero o no.

Pero en primer lugar, si el compilador debe de forma automática en línea de la función, que debe ser estática. Y debe estar contenido en la misma unidad de compilación. NOTA: estamos hablando de C, no de C++. Las reglas en línea de C++ difieren.

Si no es posible tener la función de la misma unidad de compilación, a continuación, tratar optimizaciones globales (consulte la documentación de su compilador para más detalles).

C99 le da una palabra clave "en línea", al igual que en C++. Lo cual eleva la restricción a la unidad de compilación.

Aquí hay algunos further information.

+2

Como C89 no dice nada en absoluto sobre la alineación, un compilador C89 es sin duda libre para en línea cualquier función que desee. Por supuesto, tal programa podría no enlazarse (que es el verdadero problema aquí), pero un compilador con un enlazador integrado podría evitar esto mediante la realización de un análisis de código global. –

+0

Así que supongo que un compilador puede alinear automáticamente funciones no estáticas si todos los archivos se compilan y vinculan en un solo paso en un archivo ejecutable (no en un archivo objeto o biblioteca). Bueno, vale, pero por lo general no es muy práctico;) La regla "debe ser estática" sigue siendo aplicable. – Frunsi

+1

Según la configuración del optimizador, el tamaño de la función, la frecuencia de las llamadas, etc., GCC alineará las funciones no estáticas dentro de la misma unidad de compilación. Todavía generará una función no en línea también. – ephemient

18

Una forma de saber si se inline la función es utilizar -Winline opción de gcc:

 
-Winline 
    Warn if a function can not be inlined and it was declared as inline. 
    Even with this option, the compiler will not warn about failures to inline 
    functions declared in system headers. 

    The compiler uses a variety of heuristics to determine whether or not to 
    inline a function. For example, the compiler takes into account the size 
    of the function being inlined and the amount of inlining that has already 
    been done in the current function. Therefore, seemingly insignificant 
    changes in the source program can cause the warnings produced by -Winline 
    to appear or disappear. 
+0

AWESOME discovery –

+0

Aunque arroja un montón de falsas advertencias sobre los destructores predeterminados> _ < –

-1

Esto me parece un caso clásico de la optimización prematura. ¿Tiene realmente sabe que hay un problema de rendimiento aquí? Uno que vale la pena perder su valioso tiempo de preocuparse. Quiero decir, realmente sabe? Como, ¿lo has medido?

Por sí solo esto no es tan malo, pero si adoptas esta actitud con una gran cantidad de código, puedes hacer un daño grave y desperdiciar una gran cantidad de tiempo de desarrollo y mantenimiento sin una buena razón.

+0

Como dije en la pregunta, no estoy preocupado por la optimización, estoy tratando de aprender más sobre el lenguaje y GCC. Ciertamente creo en la medición antes de optimizar, pero creo que es útil por lo menos saber estas cosas. – Joe

0

Si le preocupa que el compilador genere un código subóptimo y desee cambiar un tipo de valor simple, declare su función como int myFunction(int) y devuelva el nuevo valor.

Cuestiones relacionadas