Qual a diferença entre chamadas prováveis e improváveis no Kernel. Enquanto procurava na fonte do kernel, encontrei essas instruções.
# define likely(x) __builtin_expect(!!(x), 1)
# define unlikely(x) __builtin_expect(!!(x), 0)
Alguém poderia lançar alguma luz sobre isso?
Respostas:
Eles são dicas do compilador para o GCC. Eles são usados em condicionais para informar ao compilador se é provável que uma ramificação seja tomada ou não. Isso pode ajudar o compilador a definir o código de maneira ideal para o resultado mais frequente.
Eles são usados assim:
Deve ser usado com muito cuidado (ou seja, com base nos resultados reais de criação de perfil de ramificação). Uma dica errada pode prejudicar o desempenho (obviamente).
Alguns exemplos de como o código pode ser otimizado são facilmente encontrados procurando
GCC __builtin_expect
. Esta postagem do blog otimiza o gcc: __builtin_expect, por exemplo, detalha uma desmontagem com ele.O tipo de otimizações que pode ser feito é muito específico do processador. A idéia geral é que, frequentemente, os processadores executam o código mais rapidamente se não ramificam / saltam por todo o lugar. Quanto mais linear for, e quanto mais previsíveis forem as ramificações, mais rápido será executado. (Isso é especialmente verdadeiro para processadores com pipelines profundos, por exemplo.)
Portanto, o compilador emitirá o código de forma que a ramificação mais provável não envolva um salto, se é o que a CPU de destino prefere, por exemplo.
fonte
Vamos descompilar para ver o que o GCC 4.8 faz com ele
Sem esperar
Compile e descompile com o GCC 4.8.2 x86_64 Linux:
Resultado:
A ordem das instruções na memória permaneceu inalterada: primeiro o
printf
e depoisputs
oretq
retorno.Com esperar
Agora substitua
if (i)
por:e temos:
O
printf
(compilado para__printf_chk
) foi movido para o final da função, apósputs
e o retorno para melhorar a previsão de ramificação, conforme mencionado por outras respostas.Portanto, é basicamente o mesmo que:
Essa otimização não foi concluída
-O0
.Mas boa sorte em escrever um exemplo que é mais rápido do
__builtin_expect
que sem, as CPUs são realmente inteligentes naqueles dias . Minhas tentativas ingênuas estão aqui .C ++ 20
[[likely]]
e[[unlikely]]
O C ++ 20 padronizou os recursos internos do C ++: /programming/51797959/how-to-use-c20s-likely-unlikely-attribute-in-if-else-statement Eles provavelmente (um trocadilho!) faça a mesma coisa.
fonte