Baixe o app para aproveitar ainda mais
Prévia do material em texto
Na implementação de uma CPU comum, as instruções são executadas um após a outra, com cada ciclo de instrução sendo executado na íntegra, em todas as suas etapas. Isso faz com que partes significativas da CPU fiquem ociosas ao longo do tempo. Na busca por um melhor desempenho das CPUs, os fabricantes decidiram adaptar o conceito de linha de montagem das fabricas para o projeto das CPUs. Em uma linha de montagem, a fabricação dos produtos é dividida em várias etapas sequencias. Na “fabrica CPU” são produzidas instruções. Portanto é o “produto” instrução que é dividida em etapas de produção na linha de montagem, a pipeline, ou seja, a execução de cada instrução é dividida em etapas, ou estágios. Se a técnica for bem-sucedida, a produtividade, isto é, a quantidade de instrução executadas ao longo do tempo, deve aumentar. Para observar os ganhos da implementação do pipeline é necessário observar o funcionamento de uma CPU sem o uso da pipeline, onde as instruções são executadas sequencialmente, conforme a figura a seguir: Em uma CPU implementada com a técnica de pipeline, as instruções são divididas em estágios e inseridas na pipeline (linha da montagem), de modo que as instruções são parcialmente sobrepostas na execução. Ao longo do tempo há um ganho decorrente do aumento do fluxo de execução das instruções. Isto é, as instruções levam o mesmo tempo para serem completamente executadas, mas como elas estão parcialmente sobrepostas, basta o tempo de um estágio para que uma nova instrução termine de ser executada. É possível observar a execução das instruções em uma CPU com pipeline na figura a seguir: No exemplo, no mesmo tempo em que seriam executadas apenas 2 instruções, a CPU com pipeline teria finalizado 6 instruções, além de já ter inserido na pipeline trechos de outras 4 instruções. Os estágios apresentados no exemplo correspondem a uma das implementações mais comuns de pipeline, conforme as etapas do ciclo de instrução: • BI – Busca da instrução; • Di – decodificação da instrução; • BO – Busca do(s) operando(s); • EI – Execução da instrução; • AR- Armazenamento do(s) resultado(s); Os estágios de uma pipeline sempre têm a mesma duração, ajustada pelo estágio que leve mais tempo. Já a quantidade de estágios depende de uma série de detalhes da implementação e tem impacto no ganho de desempenho máximo teórico, que corresponde á quantidade de estágios da pipeline, mas que é apenas um referencial teórico impossível de ser mantido continuamente. O emprego da pipeline é praticamente universal nas CPUs comerciais. Mesmo CPUs extremamente simples costumam empregar pipelines de 2 estágios, correspondente aos ciclos de busca e execução. E há CPUs implementadas com pipeline de mais de 20 estágios. Ao preencher os estágios da pipeline as instruções são carregadas sequencialmente, pressupondo que a ordem das instruções na memória será seguida á risca. No entanto, isso nem sempre ocorre. Às vezes há algum problema que atrasa a linha de montagem, deixando uma ou mais etapas vazias, até que a linha possa ser totalmente recarregada. Outras vezes a linha de montagem tem que ser “limpa” e reiniciada, como se um pedido para trocar o produto produzido na linha de montagem chegasse com urgência absoluta. As situações que atrasam, ou interrompem, a pipeline são chamadas de conflitos (hazards) e o atraso gerado para resolver a cousa do conflito é chamado de pipeline stall, ou bubble (bolas). Existem 3 tipos de conflitos que acarretam em bolhas na pipeline: 1. Conflito de desvio, ou de controle; 2. Conflito de dados; 3. Conflito estrutural, ou de recurso; Quando a instrução carregada na pipeline não corresponde a instrução que deve ser executada tem-se um conflito de desvio, também chamado de conflito de controle. Ele ocorre com certa frequência porque todo programa tem alteração no fluxo das instruções, causados por laços e desvios condicionais, por exemplo. Essas situações naturalmente farão com que as instruções carregadas na linha de montagem não sirvam mais e sejam descartadas, reiniciando-se o carregamento de instruções na pipeline. Este mesmo conflito ocorre quando há um pedido de interrupção, ou quando é trocado o programa em execução em um sistema multitarefas. Em outras situações, o dado que precisa ser manipulado pela instrução seguinte na pipeline depende do resultado da instrução anterior. Por exemplo, a instrução em execução irá sobrescrever o acumulador e a próxima instrução carregada na pipeline depende desse valor. Portanto será necessário atrasar a execução dessas instrução já carregada, ate que o valor do operando esteja disponível. Essa situação é chamada de conflito de dados e gera algumas bolhas, pequenas atrasos na pipeline. Por fim, algumas vezes é o componente requerido para a execução de um determinado estágio que esta ocupado, o que constitui um conflito estrutural, também chamado de conflito de recursos. Um exemplo típico é que enquanto uma instrução busca um operando na memoria principal, o estagio de busca da instrução da pipeline não pode ser executado e precisa aguardar, acarretando em uma bolha na pipeline. Para minimizar a ocorrência de conflitos, os projetistas de CPUs desenvolveram outras técnicas bastante sofisticadas, tais como previsão de desvio e reordenação do fluxo de instrução.
Compartilhar