Eu estava lendo um documento que fala sobre técnicas de otimização do compilador just-in-time (JIT) para Java. Um deles era "inversão de loop". E o documento diz:
Você substitui um
while
loop regular por umdo-while
loop. E odo-while
loop é definido dentro de umaif
cláusula. Essa substituição leva a dois saltos a menos.
Como funciona a inversão de loop e como ela otimiza nosso caminho de código?
NB: Seria ótimo se alguém pudesse explicar com um exemplo de código Java e como o JIT o otimiza para código nativo e por que é ideal em processadores modernos.
java
jvm
jit
machine-instruction
Tentando
fonte
fonte
Respostas:
Fluxo de trabalho:
Fluxo de trabalho:
Comparando esses dois, você pode facilmente ver que o último pode não fazer nenhum salto, desde que haja exatamente uma etapa no loop e, geralmente, o número de saltos será um a menos que o número de iterações. O primeiro terá que voltar para verificar a condição, apenas para sair do loop quando a condição for falsa.
Os saltos nas arquiteturas modernas de CPU com pipeline podem ser bastante caros: como a CPU está terminando a execução das verificações antes do salto, as instruções além desse salto já estão no meio do pipeline. Todo esse processamento deve ser descartado se a previsão do branch falhar. A execução posterior é atrasada enquanto o pipeline está sendo reprimido.
Explicando a previsão de desvio mencionada : para cada tipo de salto condicional, a CPU possui duas instruções, cada uma incluindo uma aposta no resultado. Por exemplo, você colocaria uma instrução dizendo " pule se não for zero, apostando no não zero " no final de um loop, porque o salto terá que ser feito em todas as iterações, exceto na última. Dessa forma, a CPU começa a bombear seu pipeline com as instruções que seguem o destino de salto, em vez daquelas que seguem a própria instrução de salto.
Nota importante
Por favor, não tome isso como um exemplo de como otimizar ao nível do código-fonte. Isso seria totalmente equivocado, pois, como já ficou claro em sua pergunta, a transformação da primeira forma para a segunda é algo que o compilador JIT faz rotineiramente, completamente por conta própria.
fonte
do-while
código-fonte fornecido é irrelevante, porque na verdade não o escrevemos. Escrevemos owhile
loop e deixamos o compilador e o JIT conspirarem para melhorá-lo para nós (por meio da inversão do loop) se / conforme necessário.Isso pode otimizar um loop que sempre é executado pelo menos uma vez.
Um
while
loop regular sempre voltará ao início pelo menos uma vez e saltará para o final uma vez no final. Um exemplo de um loop simples executado uma vez:Um
do-while
loop, por outro lado, pulará o primeiro e o último salto. Aqui está um loop equivalente ao acima, que será executado sem saltos:fonte
boolean b = true; while(b){ b = maybeTrue();}
aboolean b;do{ b = maybeTrue();}while(b);
deve bastar.Vamos examiná-los:
A
while
versão:n
e verificamosdone();
se a condição não é verdadeira.n
.done()
.A
do-while
versão:(Lembre-se de que não fazemos isso no código-fonte [isso introduziria problemas de manutenção], o compilador / JIT faz isso por nós.)
n
e verificamosdone();
se a condição não é verdadeira.n
.done()
.Então, por exemplo, se
n
começa sendo9
, nunca pulamos nado-while
versão, enquanto nawhile
versão temos que voltar ao início, fazer o teste e depois voltar ao final quando vemos que não é verdade .fonte
A inversão de loop é uma técnica de otimização de desempenho que melhora o desempenho, pois o processador pode obter o mesmo resultado com menos instruções. Isso deve melhorar principalmente o desempenho em condições de limite.
Este link fornece outro exemplo de inversão de loop. Em algumas arquiteturas em que decremento e comparação são implementados como um único conjunto de instruções, faz sentido converter um loop for em um while com decremento e operação de comparação.
A Wikipedia tem um exemplo muito bom e estou explicando-o aqui novamente.
será convertido pelo compilador para
Como isso se traduz em desempenho? Quando o valor de i é 99, o processador não precisa realizar um GOTO (que é necessário no primeiro caso). Isso melhora o desempenho.
fonte