¿Puede la corrección constante mejorar el rendimiento?

92

He leído en numerosas ocasiones que imponer la corrección constante en su código C o C ++ no solo es una buena práctica con respecto a la capacidad de mantenimiento, sino que también puede permitir que su compilador realice optimizaciones. Sin embargo, también he leído todo lo contrario: que no afecta el rendimiento en absoluto.

Por tanto, ¿tiene ejemplos en los que la corrección const pueda ayudar a su compilador a mejorar el rendimiento de su programa?

shuhalo
fuente
50
Const-correctness es una de las MEJORES prácticas en cuanto a mantenibilidad. Si su código C ++ no es correcto const, es básicamente un montón de basura, esperando que ocurra un desastre. No tiene la intención de afectar el rendimiento.
2
@Neil Butterworth: desafortunadamente, lo contrario no es cierto.
Beta
6
Aquí hay un ejemplo donde constmarcó una diferencia de rendimiento: stackoverflow.com/questions/1121791/… . Sin embargo, fue esencialmente un problema de calidad de implementación. constno determinó si el compilador podía realizar la optimización legalmente, simplemente sucedió que la versión del compilador no pudo hacerlo cuando faltaba.
Steve Jessop
3
Estoy bastante seguro de que "morgennebel" omitió un "solo" en la primera oración: tiene mucho más sentido con "no es solo una buena práctica".
IanH
2
@IanH Sí, lo consideré. Pero el OP ha tenido tiempo suficiente para aclarar. Realmente me cabrean las personas que publican preguntas y luego simplemente desaparecen.

Respuestas:

77

constla corrección no puede mejorar el rendimiento porque const_casty mutableestán en el lenguaje, y permiten que el código rompa las reglas de forma conforme. Esto empeora aún más en C ++ 11, donde sus constdatos pueden, por ejemplo, ser un puntero a a std::atomic, lo que significa que el compilador tiene que respetar los cambios realizados por otros hilos.

Dicho esto, es trivial para el compilador observar el código que genera y determinar si realmente escribe en una variable determinada y aplicar las optimizaciones en consecuencia.

Dicho todo esto, la constcorrección es algo bueno con respecto a la mantenibilidad. De lo contrario, los clientes de su clase podrían romper los miembros internos de esa clase. Por ejemplo, considere el estándar std::string::c_str(): si no pudiera devolver un valor constante, ¡podría jugar con el búfer interno de la cadena!

No lo utilice constpor motivos de rendimiento. Úselo por razones de mantenimiento.

Billy ONeal
fuente
31
"¡Podrías jugar con el búfer interno de la cuerda!" - lo que es más importante, podría estropear accidentalmente el búfer interno. Los errores del compilador se deben a constseñales que dicen "estás haciendo algo estúpido".
Steve Jessop
4
... y const-casts son señales que dicen, "el autor de este código está tratando de hacer algo inteligente" ;-)
Steve Jessop
5
@Steve Jessop - o const-cast son señales que dicen "Estoy tratando de unir un montón de código const-correcto a uno que no-const-correcto, y no puedo arreglar ninguno". Lo cual, déjame decirte, no es de ninguna manera inteligente, solo molesto.
Michael Kohne
7
@Michael: sí, buen punto. Quizás la señal original no es "estás haciendo algo estúpido", sino "alguien está haciendo algo estúpido".
Steve Jessop
Godbolt y Arduino me dijeron que la corrección constante no es solo por diversión.
dgrat
31

Sí puede.

La mayoría de constlos mensajes de correo electrónico son puramente para el beneficio del programador y no ayudan al compilador a optimizar porque es legal desecharlos y, por lo tanto, no le dicen al compilador nada útil para la optimización. Sin embargo, algunos constmensajes de correo electrónico no se pueden descartar (legalmente) y proporcionan al compilador información útil para la optimización.

Por ejemplo, el acceso a una variable global definida con un consttipo se puede insertar en línea, mientras que uno sin un consttipo no se puede insertar en línea porque podría cambiar en tiempo de ejecución.

https://godbolt.org/g/UEX4NB

C ++:

int foo1 = 1;
const int foo2 = 2;

int get_foo1() {
    return foo1;
}

int get_foo2() {
    return foo2;
}

asm:

foo1:
        .long   1
foo2:
        .long   2
get_foo1():
        push    rbp
        mov     rbp, rsp
        mov     eax, DWORD PTR foo1[rip] ; foo1 must be accessed by address
        pop     rbp
        ret
get_foo2():
        push    rbp
        mov     rbp, rsp
        mov     eax, 2 ; foo2 has been replaced with an immediate 2
        pop     rbp
        ret

En términos prácticos, tenga en cuenta que, si bien constpuede mejorar el rendimiento, en la mayoría de los casos no lo hará o lo hará, pero el cambio no se notará. La principal utilidad de constno es la optimización.


Steve Jessop da otro ejemplo en su comentario sobre la pregunta original que trae algo que vale la pena mencionar. En el alcance de un bloque, es posible que un compilador deduzca si una variable se mutará y optimizará en consecuencia, independientemente de const, porque el compilador puede ver todos los usos de la variable. Por el contrario, en el ejemplo anterior, es imposible predecir si foo1se mutará, ya que podría modificarse en otras unidades de traducción. Supongo que un ultracompilador inteligente hipotético podría analizar un programa completo y determinar si es válido para acceder en línea foo1... pero los compiladores reales no pueden.

Praxeolítico
fuente
@ericcurtin Es por eso que no mencioné el compilador en la respuesta. Normalmente, al publicar el ensamblado generado, me aseguraría de indicar el compilador y la versión, pero esta es una optimización que realizarán todos los compiladores de optimización principales, por lo que no quería dar la impresión de que esto era particular de un compilador.
Praxeolítico
1
@Acorn Aquí está el mismo ejemplo pero con un objeto de clase: godbolt.org/z/R-Zfgc . Además, las variables del ejemplo tienen vínculos externos.
Praxeolítico
6

en mi experiencia, no

Para las variables escalares, el compilador puede determinar cuándo se cambia el valor y realizar la optimización necesaria él mismo.

Para los punteros de matriz, la corrección const no garantiza que los valores sean realmente constantes en presencia de posibles problemas de alias. Por lo tanto, el compilador no puede usar el modificador const solo para realizar optimizaciones

Si está buscando optimización, debe considerar __restrict__modificadores / atributos de funciones especiales: http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

Anycorn
fuente