:: Organização de Computadores II ::






Pipeline

A idéia do pipeline é bem simples.
imagine que você tenha de levar 4 sacas de roupa na lavanderia, lavar, secar e passar cada uma delas.

Você chega à lavanderia às 18 horas e começa o trabalho da seguinte forma:






De acordo com o desenho, vc leva 30 minutos lavando a roupa, 40 secando e 20 passando cada saco com uma certa quantidade de roupas.
Se pararmos para analizar este tempo poderia ser otimizado. Da seguinte forma:






Agora, enquanto um saco está lavando você pode secar o anterior. E como a roupa não depende de que você fique ao lado da máquina, você pode passar a leva anterior e assim otimiza o tempo.

O pipeline funciona assim. Enquanto uma instrução passa para a próxima fase, podemos otimizar o tempo pegando a próxima a ser executada.

Seria ótimo se fosse apenas isto, mas não podemos esquecer que em programas de computador temos instruções condicionais e estas podem gerar erros no pipeline, se não tratadas de maneira correta.


Vamos explicar de maneira mais técnica agora...

O Pipeline é constituído por uma seqüência de estágios operando em paralelo. A saída de um estágio serve de entrada para o seguinte.
Em um pipeline de cinco estágios, por exemplo, um estágio busca instruções, outro as decodifica, o seguinte determina os endereços dos operandos das instruções, outro busca os operandos e o última executa as instruções. (Lembram de Von Neumann?)

A seqüência de interpretação de instruções não é quebrada, mas várias instruções são processadas simultaneamente. Em um mesmo instante, uma instrução está sendo executada pelo estágio de execução, o estágio de busca de operandos procura os operandos da instrução seguinte, enquanto que o estágio de cálculo de endereços determina onde buscar os operandos de uma terceira instrução. Ao mesmo tempo, uma quarta instrução está sendo decodificada pelo estágio correspondente, enquanto que a instrução seguinte a esta é
buscada pelo estágio de busca.

Se fosse apenas isto, teríamos um pipeline perfeito. Mas...

Em instruções de desvio, o endereço da próxima instrução a ser buscada só será conhecido com certeza após a execução da instrução atual. Estudos estatísticos mostram que cerca de 30% das instruções são desvios.

Quando o pipeline processa uma instrução de desvio, o mesmo é carregado com várias instruções que podem não ser as que deveriam ser executadas após o desvio.

Esta perda de ciclos do pipeline é denominada Penalidade de Desvio. Um mecanismo de solução simples para este problema é assumir que o desvio não será realizado e buscar a instrução seguinte em PC+1.

Se a instrução for um desvio e este acontecer, é necessário restaurar a configuração original do pipeline anterior ao desvio (chama-se: fazer squashing), o que redunda em perda de desempenho.



Na figura acima, D representa os desvios do programa.

Vamos montar uma fórmula para calcular mais precisamente:

Tm = Tempo médio de interpretação de uma instrução no pipeline:
Tm = (1-Pd).(1) + Pd.[Pdr.(1+D)+(1-Pdr).(1)] = (1 + D.Pd.Pdr) ciclos.
onde:
· D = penalidade de desvio, em ciclos.
· Pd = Probabilidade de que a instrução seja um desvio.
· Pdr = Probabilidade de que, sendo a instrução um desvio, este efetivamente aconteça.
· A eficiencia do pipeline é: Ef = 1/Tm = 1/(1 + D.Pd.Pdr).

Uma maneira de aumentar a eficiência do pipeline, consiste em utilizar uma predição da maneira em que o desvio será realizado, de modo a buscar a instrução que terá mais probabilidade de sucedê-lo.

Dois tipos de predições podem ser utilizadas:
   · Predição estática (em tempo de compilação): compilador coloca a instrução seguinte mais provável logo após o desvio. Exemplo: desvios em loops tem grande probabilidade de ocorrer; desvios devidos a chamadas de rotinas de exceção tem pequena probabilidade de ocorrer.

   · Predição dinâmica (em tempo de execução): microprograma mantém tabela de endereços de destino de instruções de desvio e informações sobre o seu comportamento.


Hora de aprofundar na memória cache!

Continua >>