Eu estava lendo a resposta popular sobre a Predição de Filial em https://stackoverflow.com/q/11227809/555690 , e há algo que me confunde:
- Se você adivinhou certo, continua.
- Se você adivinhou errado, o capitão irá parar, recuar e gritar com você para apertar o botão. Em seguida, ele pode reiniciar no outro caminho.
Se você acertar sempre, o trem nunca terá que parar.
Se você adivinhar errado com muita frequência, o trem passará muito tempo parando, fazendo backup e reiniciando.
Mas é isso que eu não entendo: para saber se seu palpite estava certo ou errado, você precisa fazer uma verificação da condição de qualquer maneira . Então, como a previsão de ramificação funciona, se você ainda está fazendo a mesma verificação condicional?
O que estou tentando dizer é que a previsão de ramificação não é exatamente o mesmo que não ter nenhuma previsão de ramificação porque você está fazendo as mesmas verificações condicionais? (obviamente estou errado, mas não entendi)
fonte
Respostas:
Obviamente, a condição é verificada todas as vezes. Mas, no momento em que é verificado, já está no pipeline da CPU. Nesse meio tempo, outras instruções também entraram no pipeline e estão em vários estágios de execução.
Geralmente, uma condição é imediatamente seguida por uma instrução de ramificação condicional, que ramifica se a condição for avaliada como TRUE ou será reprovada se a condição for avaliada como FALSE. Isso significa que existem dois fluxos de instruções diferentes que podem ser carregados no pipeline após a instrução de condição e a instrução de ramificação, dependendo se a condição é avaliada como TRUE ou FALSE. Infelizmente, imediatamente após o carregamento da instrução de condição e da instrução de ramificação, a CPU ainda não sabe o que avaliará a condição, mas ainda precisará carregar o material no pipeline. Portanto, ele escolhe um dos dois conjuntos de instruções com base em um palpite sobre o que a condição avaliará.
Posteriormente, conforme a instrução de condição percorre o oleoduto, é hora de ser avaliada. Nesse momento, a CPU descobre se seu palpite estava certo ou errado.
Se o palpite estiver correto, o ramo foi para o local correto e as instruções corretas foram carregadas no pipeline. Se o palpite estiver errado, todas as instruções que foram carregadas no pipeline após a instrução de ramificação condicional estavam erradas, elas precisam ser descartadas e a busca de instruções deve começar novamente no lugar certo.
Alteração
Em resposta ao comentário do StarWeaver, para ter uma idéia do que a CPU deve fazer para executar uma única instrução:
Considere algo tão simples como o
MOV AX,[SI+10]
que nós humanos imaginamos como "carregamos o AX com a palavra SI mais 10". Aproximadamente, a CPU precisa:São 10 etapas impressionantes. Algumas dessas etapas serão otimizadas, mesmo em CPUs sem pipeline, por exemplo, a CPU quase sempre incrementará o PC em paralelo com a próxima etapa, o que é fácil, pois o PC é um registro muito, muito especial. nunca usado para qualquer outro trabalho, portanto, não há possibilidade de contenção entre diferentes partes da CPU para acessar esse registro específico. Porém, ainda temos 8 etapas para uma instrução tão simples e observe que já estou assumindo algum grau de sofisticação em nome da CPU, por exemplo, estou assumindo que não haverá necessidade de uma etapa extra inteira para o adicionador para efetivamente realizar a adição antes que o resultado possa ser lido dela,
Agora, considere que existem modos de endereçamento mais complicados, como
MOV AX, [DX+SI*4+10]
e instruções ainda mais complicadas, como osMUL AX, operand
que realmente executam loops dentro da CPU para calcular seu resultado.Portanto, meu argumento aqui é que a metáfora do "nível atômico" está longe de ser adequada ao nível de instrução da CPU. Pode ser adequado para o nível de etapa do pipeline, se você não quiser ir muito longe até o nível real da porta lógica.
fonte
MOV AX,[SI+10]
são estranhas, não "simples"; hoje a maioria dos programadores nunca escreveu montagem. Nós não "pensamos ingenuamente" como significando algo.Pense nisso como uma viagem sem GPS. Você chega a um cruzamento e acha que precisa virar, mas não tem certeza. Então você faz a curva, mas peça ao seu passageiro para verificar o mapa. Talvez você esteja a cinco quilômetros da estrada quando terminar de discutir sobre onde está. Se você estivesse certo, você está a cinco quilômetros a mais do que estaria se tivesse parado e discutido antes de virar. Se você estava errado, você tem que se virar.
Os pipelines da CPU funcionam da mesma maneira. No momento em que eles podem verificar a condição, eles já estão a caminho. A diferença é que eles não precisam dirigir os cinco quilômetros para trás, apenas perdem a vantagem. Isso significa que não há mal em tentar.
fonte
Pelo meu entendimento, a previsão de ramificação é mais útil quando a condição que você precisa verificar exige o resultado de algo caro ou ainda em andamento, e você estaria mexendo os polegares esperando o valor para avaliar a condição.
Com coisas como execução fora de ordem, você pode usar a previsão de ramificação para começar a preencher pontos vazios no pipeline que a CPU não seria capaz de usar. Em uma situação em que não há, por algum motivo, ciclos inativos no pipeline, então sim, não há ganho na previsão de ramificação.
Mas a chave aqui é que a CPU está iniciando o trabalho para uma das ramificações previstas porque ainda não pode avaliar a condição.
fonte
Forma curta:
Algumas CPUs podem começar a trabalhar em uma nova instrução antes de terminar a antiga. Estas são as CPUs que usam previsão de ramificação.
Um exemplo de pseudocódigo:
O código acima verifica uma condição e, com base no resultado, ele precisa retornar o valor armazenado no local da memória
addThis
ou o valor armazenado emreadThat
. Se a previsão de ramificação predizer a condiçãotrue
, a CPU já lerá o valor armazenado no local da memóriaaddThis
enquanto faz o cálculo necessário para avaliar aif
instrução. Este é um exemplo simplificado.fonte
Sim, a condição é verificada de qualquer maneira. Mas a vantagem da previsão de ramificação é que você pode trabalhar em vez de aguardar o resultado da verificação da condição.
Digamos que você tenha que escrever uma redação e que possa ser sobre o tópico A ou o tópico B. Você sabe de ensaios anteriores que seu professor gosta mais do tópico A do que B e o escolhe com mais frequência. Em vez de esperar pela decisão dele, você pode começar a escrever o ensaio sobre o primeiro tópico. Agora, existem dois resultados possíveis:
As CPUs modernas estão ociosas na maior parte do tempo porque aguardam respostas de E / S ou o resultado de outros cálculos. Este tempo pode ser usado para realizar alguns trabalhos futuros.
Mesmo que você precise descartar o que está fazendo neste período ocioso - é mais provável que seja mais eficaz se você tiver a capacidade de adivinhar qual caminho o programa escolherá. E as CPUs modernas têm essa capacidade.
fonte