A correção constante pode melhorar o desempenho?

92

Eu li várias vezes que impor a correção constante em seu código C ou C ++ não é apenas uma boa prática com relação à capacidade de manutenção, mas também pode permitir que seu compilador execute otimizações. No entanto, também li o oposto - que não afeta o desempenho de forma alguma.

Portanto, você tem exemplos em que const exatidão pode ajudar seu compilador a melhorar o desempenho do programa?

Shuhalo
fonte
50
A correção constante é uma das melhores práticas no que diz respeito à sustentabilidade. Se o seu código C ++ não estiver correto, ele é basicamente um monte de porcaria, esperando o desastre acontecer. Não se destina a afetar o desempenho.
2
@Neil Butterworth: infelizmente o inverso não é verdade.
Beta
6
Aqui está um exemplo onde constfez diferença no desempenho: stackoverflow.com/questions/1121791/… . No entanto, era essencialmente um problema de qualidade de implementação. constnão determinou se o compilador poderia legalmente fazer a otimização, simplesmente aconteceu que a versão do compilador não conseguiu fazê-la quando estava faltando.
Steve Jessop
3
Tenho certeza de que "morgennebel" perdeu um 'apenas' na primeira frase: faz muito mais sentido com "não é apenas uma boa prática".
IanH
2
@IanH Sim, eu considerei isso. Mas o OP teve muito tempo para esclarecer. Eu fico muito irritado com as pessoas que postam perguntas e então simplesmente desaparecem.

Respostas:

77

consta correção não pode melhorar o desempenho porque const_caste mutableestá na linguagem e permite que o código viole as regras de maneira conforme. Isso fica ainda pior em C ++ 11, onde seus constdados podem, por exemplo, ser um ponteiro para a std::atomic, o que significa que o compilador deve respeitar as alterações feitas por outras threads.

Dito isso, é trivial para o compilador olhar o código que ele gera e determinar se ele realmente grava em uma determinada variável e aplicar as otimizações de acordo.

Dito isso, a constcorreção é uma coisa boa no que diz respeito à sustentabilidade. Caso contrário, os clientes de sua classe podem quebrar os membros internos dessa classe. Por exemplo, considere o padrão std::string::c_str()- se não pudesse retornar um valor const, você seria capaz de mexer com o buffer interno da string!

Não use constpor motivos de desempenho. Use-o por motivos de manutenção.

Billy ONeal
fonte
31
"você seria capaz de mexer com o buffer interno da corda!" - crucialmente, você poderia acidentalmente mexer no buffer interno. Os erros do compilador devido a constsão sinais de aviso, dizendo: "você está fazendo algo estúpido".
Steve Jessop
4
... e const-casts são placas de sinalização dizendo, "o autor deste código está tentando fazer algo inteligente" ;-)
Steve Jessop
5
@Steve Jessop - ou const-cast são placas de sinalização que dizem "Estou tentando juntar um monte de código const-correto em um não const-correto, e não consigo consertar nenhum deles". O que, deixe-me dizer, não é nada inteligente, apenas irritante.
Michael Kohne
7
@Michael - sim, ponto justo. Talvez a indicação original não seja "você está fazendo algo estúpido", mas "alguém está fazendo algo estúpido".
Steve Jessop
Godbolt e Arduino me disseram que a correção constante não é apenas para diversão.
dgrat
31

Sim pode.

A maioria dos programas consté puramente para o benefício do programador e não ajuda o compilador a otimizar porque é legal descartá-los e, portanto, eles não informam ao compilador nada de útil para a otimização. No entanto, alguns consts não podem ser (legalmente) descartados e fornecem ao compilador informações úteis para otimização.

Como exemplo, o acesso a uma variável global definida com um consttipo pode ser sequencial, enquanto outra sem um consttipo não pode ser sequencial porque pode ser alterada em tempo de execução.

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

Em termos práticos, tenha em mente que, embora constpossa melhorar o desempenho, na maioria dos casos não vai ou vai, mas a mudança não será perceptível. A principal utilidade do constnão é a otimização.


Steve Jessop dá outro exemplo em seu comentário sobre a questão original, que traz algo que vale a pena mencionar. Em um escopo de bloco, é possível para um compilador deduzir se uma variável será mutada e otimizar de acordo, independentemente de const, porque o compilador pode ver todos os usos da variável. Em contraste, no exemplo acima, é impossível prever se ele foo1sofrerá mutação, pois pode ser modificado em outras unidades de tradução. Suponho que um ultracompilador senciente hipotético poderia analisar um programa inteiro e determinar se ele é válido para acesso embutido a foo1... mas compiladores reais não podem.

Praxeolítico
fonte
@ericcurtin É por isso que não mencionei o compilador na resposta. Normalmente, ao postar o assembly gerado, eu me certificaria de declarar o compilador e a versão, mas esta é uma otimização que todos os principais compiladores de otimização irão realizar, então eu não queria dar a impressão de que isso era particular para um compilador.
Praxeolitic
1
@Acorn Aqui está o mesmo exemplo, mas com um objeto de classe: godbolt.org/z/R-Zfgc . Além disso, as variáveis ​​no exemplo têm ligação externa.
Praxeolitic
6

na minha experiencia nao

Para variáveis ​​escalares, o compilador é capaz de determinar quando o valor é alterado e realizar a otimização necessária por si mesmo.

Para ponteiros de array, const exatidão não é garantia de que os valores sejam realmente constantes na presença de possíveis problemas de aliasing. Portanto, o compilador não pode usar o modificador const sozinho para realizar otimizações

se você estiver procurando por otimização, deve considerar __restrict__ou modificadores / atributos de funções especiais: http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

Anycorn
fonte