Eu tenho experimentado expressões const que são avaliadas em tempo de compilação. Mas eu brinquei com um exemplo que parece incrivelmente rápido quando executado em tempo de compilação.
#include<iostream>
constexpr long int fib(int n) {
return (n <= 1)? n : fib(n-1) + fib(n-2);
}
int main () {
long int res = fib(45);
std::cout << res;
return 0;
}
Quando executo esse código, leva cerca de 7 segundos para executar. Por enquanto, tudo bem. Mas quando eu mudar long int res = fib(45)
para const long int res = fib(45)
não leva nem um segundo. No meu entender, é avaliado em tempo de compilação.
Mas a compilação leva cerca de 0,3 segundos
Como o compilador pode avaliar isso tão rapidamente, mas em tempo de execução, leva muito mais tempo? Estou usando o gcc 5.4.0.
fib
. A implementação dos números de fibonacci que você possui acima é muito lenta. Tente armazenar em cache os valores da função no código de tempo de execução e será muito mais rápido.Respostas:
O compilador armazena em cache valores menores e não precisa recalcular tanto quanto a versão de tempo de execução.
(O otimizador é muito bom e gera muito código, incluindo truques com casos especiais que são incompreensíveis para mim; as recursões ingênuas de 2 ^ 45 levariam horas.)
Se você também armazenar valores anteriores:
a versão em tempo de execução é muito mais rápida que o compilador.
fonte
fib
função não tem efeitos colaterais (não faz referência a variáveis externas, a saída depende apenas de entradas), com um otimizador inteligente muito pode ser feito.Você pode achar interessante com 5.4 que a função não é completamente eliminada, você precisa de pelo menos 6.1 para isso.
Eu não acho que haja algum cache acontecendo. Estou convencido de que o otimizador é inteligente o suficiente para provar relação entre
fib(n - 2)
efib(n-1)
e evita a segunda chamada completamente. Esta é a saída do GCC 5.4 (obtida do godbolt) semconstexpr
e -O2:Devo admitir que não entendo a saída com -O3 - o código gerado é surpreendentemente complexo, com muitos acessos à memória e aritmética de ponteiros e é bem possível que exista algum cache (memorização) feito com essas configurações.
fonte