tecnicas site realizarse page optimizacion onpage off define debe como auditoria antes c optimization gcc compiler-construction

c - site - seo off page



¿Cuántos niveles de optimización de GCC hay? (4)

Cuatro (0-3): Consulte el manual GCC 4.4.2. Cualquier cosa más alta es solo -O3, pero en algún momento se desbordará el límite de tamaño variable.

¿Cuántos niveles de optimización de GCC hay?

Probé gcc -O1, gcc -O2, gcc -O3 y gcc -O4

Si uso un número realmente grande, no funcionará.

Sin embargo, lo he intentado

gcc -O100

y compilado.

¿Cuántos niveles de optimización hay?


Para ser pedante, hay 8 opciones -O válidas diferentes que puedes dar a gcc, aunque hay algunas que significan lo mismo.

La versión original de esta respuesta indicó que había 7 opciones. Desde entonces, GCC ha agregado -Og para llevar el total a 8

Desde la página man:

  • -O (Igual que -O1 )
  • -O0 (no hacer optimización, por defecto si no se especifica ningún nivel de optimización)
  • -O1 (optimizar al mínimo)
  • -O2 (optimizar más)
  • -O3 (optimizar aún más)
  • -Ofast (optimizar de forma muy agresiva hasta el punto de romper el cumplimiento estándar)
  • -Og (Optimice la experiencia de depuración. -Og habilita optimizaciones que no interfieren con la depuración. Debe ser el nivel de optimización de elección para el ciclo de compilación-compilación-depuración estándar, que ofrece un nivel razonable de optimización manteniendo una compilación rápida y una buena depuración experiencia.)
  • -Os (Optimizar para el tamaño. -Os habilita todas -O2 optimizaciones de -O2 que normalmente no aumentan el tamaño del código. También realiza optimizaciones adicionales diseñadas para reducir el tamaño del código. -Os los siguientes indicadores de optimización: -falign-functions -falign-jumps -falign-loops -falign-labels -freorder-blocks -freorder-blocks-and-partition -fprefetch-loop-arrays -ftree-vect-loop-version )

También puede haber optimizaciones específicas de la plataforma, como notas de @pauldoo, OS X tiene -Oz


Siete niveles distintos:

  • -O0 (predeterminado): sin optimización.

  • -O o -O1 (lo mismo): optimiza, pero no gastes demasiado tiempo.

  • -O2 : Optimizar más agresivamente

  • -O3 : Optimizar de forma más agresiva

  • -Ofast : Equivalente a -O3 -ffast-math . -ffast-math activa optimizaciones de punto flotante que no cumplen con los estándares. Esto le permite al compilador pretender que los números de punto flotante son infinitamente precisos, y que el álgebra en ellos sigue las reglas estándar del álgebra de números reales. También le dice al compilador que le diga al hardware que purgue los denormales a cero y trate los denormales como cero, al menos en algunos procesadores, incluidos x86 y x86-64. Los denormales desencadenan un camino lento en muchas FPU, por lo que tratarlos como cero (que no desencadena la ruta lenta) puede ser una gran ganancia de rendimiento.

  • -Os : Optimizar para el tamaño del código. Esto en realidad puede mejorar la velocidad en algunos casos, debido a un mejor comportamiento de I-caché.

  • -Og : Optimiza, pero no interfiere con la depuración. Esto permite un rendimiento no embarazoso para las compilaciones de depuración y está destinado a reemplazar -O0 para -O0 de depuración.

También hay otras opciones que no están habilitadas por ninguno de estos y deben habilitarse por separado. También es posible utilizar una opción de optimización, pero deshabilitar los indicadores específicos habilitados por esta optimización.

Para obtener más información, consulte el sitio web de GCC.


Interpretemos el código fuente de GCC 5.1 para ver qué sucede en -O100 ya que no está claro en la página de manual.

Concluiremos que:

  • cualquier cosa por encima de INT_MAX hasta INT_MAX es lo mismo que -O3 , pero eso podría cambiar fácilmente en el futuro, así que no confíe en ello.
  • GCC 5.1 ejecuta un comportamiento indefinido si ingresa enteros más grandes que INT_MAX .
  • el argumento solo puede tener dígitos, o falla con gracia. En particular, esto excluye enteros negativos como -O-1

Centrarse en los subprogramas

Primero recuerde que GCC es solo un front-end para cpp , as , cc1 , collect2 . Un rápido ./XXX --help dice que solo collect2 y cc1 toman -O , así que centrémonos en ellos.

Y:

gcc -v -O100 main.c |& grep 100

da:

COLLECT_GCC_OPTIONS=''-O100'' ''-v'' ''-mtune=generic'' ''-march=x86-64'' /usr/local/libexec/gcc/x86_64-unknown-linux-gnu/5.1.0/cc1 [[noise]] hello_world.c -O100 -o /tmp/ccetECB5.

por lo tanto, se reenvió a cc1 y collect2 .

O en common.opt

common.opt es un formato de descripción de opción CLI específico de GCC descrito en la documentación interna y traducido a C por opth-gen.awk y optc-gen.awk .

Contiene las siguientes líneas interesantes:

O Common JoinedOrMissing Optimization -O<number> Set optimization level to <number> Os Common Optimization Optimize for space rather than speed Ofast Common Optimization Optimize for speed disregarding exact standards compliance Og Common Optimization Optimize for debugging experience rather than speed or size

que especifica todas las opciones O Observe cómo -O<n> está en una familia separada de los otros Os , Ofast y Og .

Cuando construimos, esto genera un archivo options.h que contiene:

OPT_O = 139, /* -O */ OPT_Ofast = 140, /* -Ofast */ OPT_Og = 141, /* -Og */ OPT_Os = 142, /* -Os */

Como beneficio adicional, mientras buscamos /bO/n dentro de common.opt notamos las líneas:

-optimize Common Alias(O)

que nos enseña que --optimize (doble guion porque comienza con un guion - -optimize en el archivo .opt ) es un alias no documentado para -O que se puede usar como --optimize=3 !

Donde se usa OPT_O

Ahora grep:

git grep -E ''/bOPT_O/b''

que nos señala dos archivos:

Busquemos primero opts.c

opts.c: optimización_opciones_optimización

Todos los usos opts.c ocurren dentro de: default_options_optimization .

Nos volvemos rápidamente para ver quién llama a esta función, y vemos que la única ruta de código es:

  • main.c:main
  • toplev.c:toplev::main
  • opts-global.c:decode_opts
  • opts.c:default_options_optimization

y main.c es el punto de entrada de cc1 . ¡Bueno!

La primera parte de esta función:

  • hace integral_argument que llama atoi en la cadena correspondiente a OPT_O para analizar el argumento de entrada
  • almacena el valor dentro de opts->x_optimize donde opts es una struct gcc_opts .

struct gcc_opts

Después de desgranar en vano, notamos que esta struct también se genera en options.h :

struct gcc_options { int x_optimize; [...] }

donde x_optimize proviene de las líneas:

Variable int optimize

presente en common.opt , y esa options.c :

struct gcc_options global_options;

así que supongo que esto es lo que contiene el estado global de la configuración completa, y int x_optimize es el valor de optimización.

255 es un máximo interno

en opts.c:integral_argument , atoi se aplica al argumento de entrada, por lo que INT_MAX es un límite superior. Y si pone algo más grande, parece que GCC ejecuta C comportamiento indefinido. ¿Ay?

integral_argument también ajusta atoi y rechaza el argumento si cualquier carácter no es un dígito. Entonces los valores negativos fallan con gracia.

Volviendo a opts.c:default_options_optimization , vemos la línea:

if ((unsigned int) opts->x_optimize > 255) opts->x_optimize = 255;

de modo que el nivel de optimización se trunca a 255 . Mientras leía opth-gen.awk me opth-gen.awk con:

# All of the optimization switches gathered together so they can be saved and restored. # This will allow attribute((cold)) to turn on space optimization.

y en las options.h generadas.h:

struct GTY(()) cl_optimization { unsigned char x_optimize;

lo que explica por qué el truncamiento: las opciones también deben reenviarse a cl_optimization , que usa un char para ahorrar espacio. Entonces 255 es un máximo interno en realidad.

opts.c: maybe_default_options

Volviendo a opts.c:default_options_optimization , nos encontramos con maybe_default_options que suena interesante. Lo ingresamos, y luego maybe_default_option donde alcanzamos un gran cambio:

switch (default_opt->levels) { [...] case OPT_LEVELS_1_PLUS: enabled = (level >= 1); break; [...] case OPT_LEVELS_3_PLUS: enabled = (level >= 3); break;

No hay >= 4 controles, lo que indica que 3 es el mayor posible.

Luego buscamos la definición de OPT_LEVELS_3_PLUS en common-target.h :

enum opt_levels { OPT_LEVELS_NONE, /* No levels (mark end of array). */ OPT_LEVELS_ALL, /* All levels (used by targets to disable options enabled in target-independent code). */ OPT_LEVELS_0_ONLY, /* -O0 only. */ OPT_LEVELS_1_PLUS, /* -O1 and above, including -Os and -Og. */ OPT_LEVELS_1_PLUS_SPEED_ONLY, /* -O1 and above, but not -Os or -Og. */ OPT_LEVELS_1_PLUS_NOT_DEBUG, /* -O1 and above, but not -Og. */ OPT_LEVELS_2_PLUS, /* -O2 and above, including -Os. */ OPT_LEVELS_2_PLUS_SPEED_ONLY, /* -O2 and above, but not -Os or -Og. */ OPT_LEVELS_3_PLUS, /* -O3 and above. */ OPT_LEVELS_3_PLUS_AND_SIZE, /* -O3 and above and -Os. */ OPT_LEVELS_SIZE, /* -Os only. */ OPT_LEVELS_FAST /* -Ofast only. */ };

¡Decir ah! Este es un fuerte indicador de que solo hay 3 niveles.

opts.c: default_options_table

opt_levels es tan interesante que grep OPT_LEVELS_3_PLUS , y nos encontramos con opts.c:default_options_table :

static const struct default_options default_options_table[] = { /* -O1 optimizations. */ { OPT_LEVELS_1_PLUS, OPT_fdefer_pop, NULL, 1 }, [...] /* -O3 optimizations. */ { OPT_LEVELS_3_PLUS, OPT_ftree_loop_distribute_patterns, NULL, 1 }, [...] }

así que aquí es donde está codificada la asignación de optimización " -On a la optimización específica mencionada en los documentos. ¡Bonito!

Asegúrate de que no hay más usos para x_optimize

El uso principal de x_optimize fue establecer otras opciones de optimización específicas como -fdefer_pop como se documenta en la página del manual. ¿Hay más?

Nos grep , y encontramos algunos más. El número es pequeño, y luego de la inspección manual vemos que cada uso solo tiene un máximo de x_optimize >= 3 , por lo que nuestra conclusión es válida.

lto-wrapper.c

Ahora vamos por la segunda aparición de OPT_O , que estaba en lto-wrapper.c .

LTO significa Link Time Optimization, que como su nombre indica va a necesitar una opción -O , y estará vinculado a collec2 (que básicamente es un enlazador).

De hecho, la primera línea de lto-wrapper.c dice:

/* Wrapper to call lto. Used by collect2 and the linker plugin.

En este archivo, las apariciones de OPT_O parecen normalizar el valor de O para pasarlo, por lo que deberíamos estar bien.