Baixe o app para aproveitar ainda mais
Prévia do material em texto
2.3 Dependências de dados (Data Hazards) Ocorre quando uma instrução depende do resultado de outra instrução que ainda está no pipeline. Este tipo de dependência é originado na natureza seqüencial do código em execução, cuja ordem normal é alterada dentro do pipeline. Exemplo: CC1 CC2 CC3 CC4 CC5 CC6 CC7 CC8 CC9 ADD $s0, $t0, $t1 IF ID EX MEM WB SUB $t2, $s0, $t3 IF Stall Stall ID EX MEM WB No exemplo acima, pode-se ver que a instrução SUB precisa ler o conteúdo dos registradores no ciclo 3 mas o valor correto do registrador $s0 somente será atualizado no ciclo 5. A ação desencadeada é a parada (Stall) do estágio IF do pipeline até que o valor de $s0 esteja disponível. Caso contrário, o valor lido em $s0 não corresponderia à seqüência originalmente projetada para o código. Solução em hardware para a dependência de dados O problema de dependência de dados mostrado no exemplo pode ser resolvido com uma técnica de hardware chamada de adiantamento de dados (forwarding ou bypassing). Uma observação mais detalhada da estrutura do pipeline mostra que o valor de $s0 é realmente necessário no ciclo EX da instrução SUB e o novo valor de $s0 é calculado no ciclo EX da instrução ADD. Uma modificação no hardware (adiantamento) permite que o resultado obtido em um estágio do pipeline seja repassado para estágios anteriores (ou o próprio estágio que o produziu) antes de ser definitivamente atualizado. O comportamento do pipeline com dependências de dados e com adiantamento pode ser isto nos arquivos F0636.pdf e F0637.pdf. Exemplo: O diagrama a seguir mostra o resultado do adiantamento dos dados para o exemplo anterior. Os estágios ressaltados mostram o caminho dos dados dentro do pipeline. CC1 CC2 CC3 CC4 CC5 CC6 CC7 CC8 CC9 ADD $s0, $t0, $t1 IF ID EX MEM WB SUB $t2, $s0, $t3 IF ID EX MEM WB Apesar de resolver o problema da dependência de dados na maior parte dos casos, a técnica do adiantamento não evita a parada do pipeline em um seqüência de instruções específica. Exemplo: CC1 CC2 CC3 CC4 CC5 CC6 CC7 CC8 CC9 LW $s0, 20($t1) IF ID EX MEM WB SUB $t2, $s0, $t3 IF ID Stall EX MEM WB A parada no pipeline sempre ocorrerá quando uma instrução acessar o conteúdo de um registrador que deve ser lido na memória pela instrução imediatamente anterior. Como mostrado no diagrama anterior, o novo valor do registrador $s0 somente estará disponível Capítulo 2 – Arquiteturas SISD de alto desempenho 2 no final do ciclo 4 e a instrução SUB realmente necessita de $s0 no início do ciclo 4. Este tipo de seqüência origina o chamado pipeline interlock. Os arquivos F0644.pdf e F0645.pdf ilustram a ocorrência de um pipeline interlock. Classificação de dependências de dados: RAW (Read After Write) – ocorre quando a instrução i+1 tenta ler um dado que a instrução i ainda não atualizou; WAW (Write After Write) – ocorre quando a instrução i+1 tenta escrever um dado antes que a instrução i atualize o mesmo; WAR (Write After Read) – ocorre quando a instrução i+1 tenta escrever um dado antes que a instrução i possa lê-lo; RAR (Read After Read) – não é uma dependência. As dependências do tipo WAW e RAW não ocorrem no tipo de pipeline estudado até agora, em que todas as instruções são executados nos mesmos passos. Solução em software para as dependências de dados Agendamento por compilador: vários tipos de dependências de dados são muito comuns. Um padrão típico de código para a equação A = B + C (variáveis em memória) gera uma dependência de dados. CC1 CC2 CC3 CC4 CC5 CC6 CC7 CC8 CC9 LW $s1, B IF ID EX MEM WB LW $s2, C IF ID EX MEM WB ADD $s3, $s1, $s2 IF ID Stall EX MEM WB SW A, $s3 IF Stall ID EX MEM WB Para evitar a necessidade de parada em estágios do pipeline é possível que o compilador reorganize o código de forma que as instruções LW e ADD não ocorrem na seqüência direta. Esta técnica é chamada de agendamento (pipeline scheduling ou instruction scheduling). Exemplo: Considere o código gerado para execução das equações a = b + c; d = e – f; CC1 CC2 CC3 CC4 CC5 CC6 CC7 CC8 CC9 CC10 CC11 CC12 CC13 LW $s1, b IF ID EX MEM WB LW $s2, c IF ID EX MEM WB ADD $s3, $s1, $s2 IF ID Stall EX MEM WB SW a, $s3 IF Stall ID EX MEM WB LW $s4, e IF ID EX MEM WB LW $s5, f IF ID EX MEM WB SUB $s6, $s4, $s5 IF ID Stall EX MEM WB SW d, $s6 IF Stall ID EX MEM Capítulo 2 – Arquiteturas SISD de alto desempenho 3 Com a reorganização do código é possível eliminar as paradas. A seguir está mostrado o código reorganizado. CC1 CC2 CC3 CC4 CC5 CC6 CC7 CC8 CC9 CC10 CC11 CC12 CC13 LW $s1, b IF ID EX MEM WB LW $s2, c IF ID EX MEM WB LW $s4, e IF ID EX MEM WB ADD $s3, $s1, $s2 IF ID EX MEM WB LW $s5, f IF ID EX MEM WB SW a, $s3 IF ID EX MEM WB SUB $s6, $s4, $s5 IF ID EX MEM WB SW d, $s6 IF ID EX MEM WB A reorganização somente é possível através do uso de diferentes registradores, e a aplicação da técnica pode acarretar um aumento na alocação de registradores em relação ao código não reorganizado. 2.4 Dependências de controle (Control Hazards) As dependências de controle ocorrem quando a seqüência normal de execução das instruções é modificada. Tal modificação pode ser originada pelo próprio programa ou pode ser conseqüência de uma interrupção. As instruções de desvio condicional podem ou não alterar a seqüência natural de execução das instruções. Ao se observar a estrutura do pipeline estudado, pode-se verificar que a decisão sobre o desvio ou não somente ocorre no estágio MEM. Exemplo: O primeiro diagrama mostra o comportamento do pipeline devido a um desvio condicional não tomado (untaken). CC1 CC2 CC3 CC4 CC5 CC6 CC7 CC8 CC9 CC10 CC11 CC12 CC13 ADD $s3, $s2, $s1 IF ID EX MEM WB BEQ $s4, $s5, 100 IF ID EX MEM WB LW $s4, e IF Stall Stall IF ID EX MEM WB LW $s5, f IF ID EX MEM WB ... SUB $s4, $s1, $t5 SW $t4, 500($s0) O segundo diagrama mostra o comportamento do pipeline devido a um desvio condicional tomado (taken), em que a instrução SUB é o início da nova seqüência de instruções. CC1 CC2 CC3 CC4 CC5 CC6 CC7 CC8 CC9 CC10 CC11 CC12 CC13 ADD $s3, $s2, $s1 IF ID EX MEM WB BEQ $s4, $s5, 100 IF ID EX MEM WB LW $s4, e IF Stall Stall LW $s5, f ... SUB $s4, $s1, $t5 IF ID EX MEM WB SW $t4, 500($s0) IF ID EX MEM WB Capítulo 2 – Arquiteturas SISD de alto desempenho 4 Redução dos atrasos nos desvios Como pode ser observado nos diagramas, a penalidade devido a desvios condicionais é de 3 ciclos. Para minimizar o impacto deste tipo de instrução duas abordagens podem ser tentadas: - descobrir mais cedo se um desvio será tomado ou não tomado; - calcular o endereço de desvio mais cedo. Estas duas alternativas podem ser contempladas com algumas alterações no hardware, de forma que o circuito para o cálculo do novo valor do PC passe a operar no segundo estágio assim como o circuito de decisão do desvio. O resultado pode ser isto no diagrama a seguir. Exemplo: CC1 CC2 CC3 CC4 CC5 CC6 CC7 CC8 CC9 CC10 CC11 CC12 CC13 ADD $s3, $s2, $s1 IF ID EX MEM WB BEQ $s4, $s5, 100 IF ID EX MEM WB LW $s4, e IF LW $s5, f ... SUB $s4, $s1, $t5 IF ID EX MEM WB SW $t4, 500($s0) IF ID EX MEM WB Apesar de diminuir a penalidade para 1 ciclo nos casos comuns, a existência de uma instrução de desvio condicionada a um dado, logo após uma operação aritmética que o calcula acrescenta uma dependência de dados ao problema. Um exemplo deste caso pode ser visto no diagrama abaixo: Exemplo: CC1 CC2 CC3 CC4 CC5 CC6 CC7 CC8 CC9 CC10 CC11 CC12 CC13 ADD $s3, $s2, $s1 IF ID EX MEM WB BEQ $s3, $s5, 100 IF ID EX MEM WB LW $s4, e IF Stall LW $s5, f ... SUB $s4, $s1, $t5 IF ID EX MEM WB SW $t4, 500($s0) IF ID EX MEM WB Previsão de desvios A modificação do hardware para minimizar a penalidade de instruções de salto tem uma bom resultado no pipeline estudado (MIPS) mas muitas arquiteturas com pipelines mais longos podem sofrer uma penalidade muito maior. Isto acaboumotivando a utilização de uma outra alternativa nas dependências de controle, chamada de previsão de desvios (branch prediction). A forma mais simples de previsão é assumir que todos os desvios condicionais vão Capítulo 2 – Arquiteturas SISD de alto desempenho 5 ser não tomados e permitir que o pipeline continue a execução normal das instruções seguintes à instrução de desvio. Se a previsão se concretiza, não existe nenhuma penalidade para o desvio, mas se a previsão falha então as instruções após à instrução de desvio devem ser anuladas no pipeline, em uma operação chamada flushing. Exemplo: Considere o diagrama abaixo referente a um pipeline com previsão de desvio não tomado (untaken), no qual a previsão é correta. CC1 CC2 CC3 CC4 CC5 CC6 CC7 CC8 CC9 CC10 CC11 CC12 CC13 ADD $s3, $s2, $s1 IF ID EX MEM WB BEQ $s4, $s5, 100 IF ID EX MEM WB LW $s4, e IF ID EX MEM WB LW $s5, f IF ID EX MEM WB ... SUB $s4, $s1, $t5 SW $t4, 500($s0) O segundo diagrama mostra o comportamento do mesmo pipeline quando o desvio é tomado (taken), ou seja, a previsão foi incorreta. Considerar a instrução SUB como o destino do desvio. CC1 CC2 CC3 CC4 CC5 CC6 CC7 CC8 CC9 CC10 CC11 CC12 CC13 ADD $s3, $s2, $s1 IF ID EX MEM WB BEQ $s4, $s5, 100 IF ID EX MEM WB LW $s4, e IF Flush Flush Flush Flush LW $s5, f ... SUB $s4, $s1, $t5 IF ID EX MEM WB SW $t4, 500($s0) IF ID EX MEM WB Desvios atrasados Uma terceira alternativa para reduzir a penalidade nos desvios é chamada de desvio atrasado (delayed branch). Nesta técnica, a instrução seguinte à de desvio é executada sempre, havendo o desvio ou não. Exemplo: CC1 CC2 CC3 CC4 CC5 CC6 CC7 CC8 CC9 CC10 CC11 CC12 CC13 BEQ $s4, $s5, 100 IF ID EX MEM WB ADD $s3, $s2, $s1 IF ID EX MEM WB LW $s4, e IF ID EX MEM WB LW $s5, f IF ID EX MEM WB ... SUB $s4, $s1, $t5 IF ID EX MEM WB SW $t4, 500($s0) IF ID EX MEM WB Como pode ser visto no diagrama acima, a instrução ADD foi deslocada de forma que ocorrendo ou não o desvio (as duas alternativas são mostradas) não haja penalidade. A responsabilidade de escolha da instrução sucessora do desvio é do compilador, e algumas Capítulo 2 – Arquiteturas SISD de alto desempenho 6 otimizações são possíveis (arquivo F0654.pdf). Os compiladores tipicamente conseguem preencher com instruções úteis apenas 50% dos espaços após os desvios. Conforme comentado anteriormente, pipelines mais longos podem não se beneficiar totalmente desta técnica pois seria necessário mais do que uma instrução sucedendo o desvio. Previsão estática de desvios A previsão estática de desvios é aquela que pode ser feita em tempo de compilação. Muitos métodos de agendamento por compilador necessitam da previsão estática de desvios. Esta previsão é baseada em valores estatísticos, determinados através da análise de comportamento do código ou através da execução prévia do mesmo (profile based prediction). A seguir é apresentado um trecho de código: LW $s1, 0($s2)0 SUB $s1, $s1, $s3 BEQ $s2, $s1, L OR $s4, $s5, $s6 ADD $s10, $s4, $s3 L: ADD $s7, $s8, $s9 Neste trecho existe uma dependência entre LW, SUB e BEQ, a qual causaria um stall após LW. Se existe uma grande probabilidade do desvio ser tomado, então a última instrução do trecho pode ser a sucessora de LW, desde que $s7 não seja utilizado no caminho não tomado. Se existe uma grande probabilidade do desvio ser não tomado então a instrução OR pode ser a sucessora de LW, desde $s4 não seja utilizado no caminho tomado. As duas alternativas são vistas a seguir. Previsto tomado Previsto não tomado LW $s1, 0($s2) LW $s1, 0($s2) ADD $s7, $s8, $s9 OR $s4, $s5, $s6 SUB $s1, $s1, $s3 SUB $s1, $s1, $s3 BEQ $s2, $s1, L BEQ $s2, $s1, L OR $s4, $s5, $s6 ADD $s10, $s4, $s3 ADD $s10, $s4, $s3 L: ADD $s7, $s8, $s9 L: New instruction Previsão dinâmica de desvios Os métodos de previsão dinâmica de desvios procuram lidar com a variação de comportamento das instruções de desvio durante a execução dos programas. Estas previsões são feitas em hardware ao contrário das previsões estáticas. O método mais simples de previsão é chamado de branch history table (BHT) e consiste em uma pequena memória indexada por parte do endereço da instrução de desvio. Tal memória armazena um bit que indica se o desvio foi tomado ou não tomado no último acesso. Um dos problemas com este tipo de previsão é a possibilidade de mais de uma instrução alterar o mesmo bit dentro da BHT. Capítulo 2 – Arquiteturas SISD de alto desempenho 7 Uma evolução deste método de previsão é um esquema de BHT com dois bits. Neste caso, é preciso que a previsão seja errada duas vezes seguidas para que seja modificada. A figura a seguir mostra os estados de um esquema BHT de dois bits. A memória de previsão de desvio pode ser implementada como uma pequena cache durante o ciclo de busca (IF). Este esquema é bastante útil para uma série de arquiteturas mas não para o pipeline estudado, pois o endereço de desvio somente é definido no final do ciclo ID. Uma forma de reduzir esta penalidade é através da extensão da BHT para uma implementação chamada de branch-target buffer (BTB). Neste tipo de memória, além dos bits de previsão de desvio, também são armazenados os prováveis endereços de destino no caso de um desvio tomado. 2.5 Pipeline com suporte para operações multiciclo Certas operações de uma arquitetura não podem ser realizadas em apenas um ciclo, como devem ser as operações em um pipeline. As operações realizadas sobre números de ponto flutuante são um exemplo. Para dar suporte a este tipo de operação vamos considerar que várias unidades funcionais (EX) estarão disponíveis e poderão operar em paralelo. A seguir estão caracterizadas estas unidades no pipeline estudado. Prever tomado Prever tomado Prever não tomado Prever não tomado tomado tomado tomado tomado não tomado não tomado não tomado não tomado IF ID MEM WB EX Integer unit EX FP/integer multiply EX FP adder EX FP/integer divider Capítulo 2 – Arquiteturas SISD de alto desempenho 8 Os estágios acrescentados na figura anterior são dedicados a determinadas operações, que utilizam repetidamente os referidos estágios durante alguns ciclos. Assim, por exemplo, se uma multiplicação de números inteiros pode ser dividida em cinco etapas, a respectiva unidade será utilizada por cinco ciclos. Para evitar os possíveis hazards estruturais, as unidades acrescentadas podem ter a sua estrutura implementada com uma arquitetura pipeline. A figura abaixo mostra como ficaria a estrutura do pipeline com suporte a operações multiciclos. Note que a unidade de divisão necessita de 15 ciclos para o cálculo e tal unidade não é pipeline. A seguir está mostrado o diagrama de temporização para duas das unidades acrescentadas. Os estágios representados em itálico indicam onde os operandos são necessários e os estágios em negrito indicam onde os resultados são fornecidos: CC1 CC2 CC3 CC4 CC5 CC6 CC7 CC8 CC9 CC10 CC11 CC12 CC13 MULTD IF ID M1 M2 M3 M4 M5 M6 M7 MEM WB ADDD IF ID A1 A2 A3 A4 MEM WB LD IF ID EX MEM WB SD IF ID EX MEM WB Uma estrutura pipeline com operações multiciclo como a mostrada acima introduz uma série de aspectos que não estavam presentes no pipeline original: - possibilidade de dependência estrutural devido a unidade de divisão não pipeline; - como existem instruções com tempos de execução diferentes é possível que ocorra a necessidade de escrita em mais de um registrador no mesmo ciclo; - dependências do tipo WAW podem ocorrer, pela mesma razão anterior; - as instruções podem ser finalizadas em uma ordem diferente da ordem pré-definida; - existe uma maior probabilidade de dependências do tipo RAW e a penalidade (número de ciclos de stall) neste caso é maior. Considere os trechos de código a seguir e desenvolva o diagrama de temporização IF ID MEM WB M1 M2 M3 M4 M5 M6 M7 A1A2 A3 A4 EX DIV Capítulo 2 – Arquiteturas SISD de alto desempenho 9 para o pipeline multiciclos: Trecho 1 Trecho 2 LD F4, 0(R2) MULTD F0, F4, F6 MULTD F0, F4, F6 .... ADDD F2, F0, F8 .... SD F2, 0(R2) ADDD F2, F4, F6 .... .... LD F8, 0(R2) 2.6 Arquiteturas Superescalares Como visto nas seções anteriores, as arquiteturas pipeline implementam uma espécie de paralelismo (parcial) entre instruções, o que, no melhor dos casos, permite um desempenho de execução de 1 instrução por ciclo (1 IPC – Instruction Per Cycle). As alternativas para aumentar o desempenho de uma arquitetura são as seguintes: - Superpipelining; - Superescalaridade; - Very Long Instruction Word (VLIW). 2.6.1 Superpipelining A filosofia do superpipeline está baseada no fato de que muitos dos estágios de um pipeline podem operar em um tempo menor que a metade de um ciclo de clock. Assim, a estrutura do pipeline pode operar em uma freqüência que é o dobro da freqüência do restante do processador, permitindo a execução de duas instruções durante o período de um ciclo de clock externo. Neste caso o superpipeline é chamado de grau 2, mas superpipelines de maior grau são possíveis. A designação superpipeline está associado a pipelines com muitos estágios (>8), ou seja, pipelines profundos. 2.6.2 Superescalaridade O termo superescalar diz respeito às arquiteturas projetadas para executar múltiplas instruções escalares simultaneamente. Isto quer dizer que múltiplas unidades funcionais são necessárias e que múltiplos pipelines estarão operando em paralelo. A grande maioria dos processadores atuais está baseada em arquiteturas superescalares. Arquiteturas superescalares de n vias de execução podem atingir um desempenho máximo de n IPC. Assim, uma arquitetura de 4 vias de execução pode executar até 4 instruções por ciclo. Desempenho (IPC) = n° instruções executadas / n° ciclos decorridos Desempenho (CPI) = n° ciclos decorridos / n° instruções executadas Capítulo 2 – Arquiteturas SISD de alto desempenho 10 Uma estrutura de máquina superescalar pode ser vista a seguir. No exemplo mostrado, uma unidade de busca despacha um par de instruções para os respectivos pipelines. Para que uma máquina seja realmente paralela, todos os recursos de hardware devem ser duplicados, mas isto não é o que acontece com muitas máquinas reais. Nestas, apenas algumas instruções podem executar em paralelo ou certos tipos de instruções podem executar em paralelo. A figura a seguir mostra um diagrama comparativo do comportamento de três arquiteturas: pipeline normal, superpipeline de grau 2 e superescalar de 2 vias de execução. Pipeline normal Superpipeline Superescalar Assim como as dependências limitam o desempenho de um pipeline, o mesmo ocorre com uma arquitetura superescalar. O resultado de uma abordagem de execução paralela depende do grau no qual as instruções de um programa podem ser executadas em paralelo, o que é conhecido por paralelismo a nível de instruções (ILP – instruction-level parallelism). Como visto nas seções anteriores, uma combinação de técnicas de hardware com otimizações baseadas em software (compilador) pode melhorar o ILP. Deve ser feita uma distinção entre ILP e paralelismo de máquina. O ILP ocorre quando as instruções de uma seqüência de código são independentes e podem ser executadas em paralelo. O paralelismo Instruction fetch unit Operand fetch unit Instruction decode unit Instruction execution unit Write back unit Operand fetch unit Instruction decode unit Instruction execution unit Write back unit Capítulo 2 – Arquiteturas SISD de alto desempenho 11 de máquina é a medida da capacidade do processador de utilizar efetivamente o ILP. Os trechos de código a seguir exemplificam o conceito de ILP: Trecho 1 Trecho 2 Load R1 ¬ R2 Add R3 ¬ R3, 1 Add R3 ¬ R3, 1 Add R4 ¬ R3, R2 Add R4 ¬ R4, R2 Store [R4] ¬ R0 As três instruções do trecho 1 são independentes e teoricamente as três podem ser executadas em paralelo. As três instruções do trecho 2 são dependentes entre si e não podem ser executadas em paralelo. ILP e paralelismo de máquina são fatores importantes para o ganho de desempenho. Isto quer dizer que não basta uma máquina dispor de imensos recursos de hardware para que se atinja um imenso desempenho. Uma das principais tarefas de um processador superescalar é a identificação do ILP de uma aplicação, para o adequado gerenciamento da busca, decodificação e execução paralela das instruções. Política de despacho de instruções O termo “despacho de instrução” (instruction-issue) refere-se à operação de envio de uma instrução para a respectiva unidade funcional. Na realidade, o processador busca antecipadamente as instruções de forma que possa determinar quais realmente podem ser executadas pelo pipeline. Existem três tipos de ordem nas operações em um processador: - a ordem na qual as instruções são buscadas; - a ordem na qual as instruções são executadas; - a ordem na qual as instruções atualizam os registradores e a memória. Quanto mais sofisticado o processador, menos relacionados estão estes ordenamentos. Para otimizar a utilização dos vários estágios dos pipelines, o processador pode ser forçado a alterar um ou mais destes ordenamentos em relação a uma execução puramente seqüencial. Assim, o processador pode acomodar as várias dependências discutidas anteriormente. A única e óbvia restrição é que os resultados devem ser corretos. As políticas de despacho de instruções para arquiteturas superescalares podem ser classificadas como: - despacho em ordem e término em ordem; - despacho em ordem com término fora de ordem; - despacho fora de ordem com término fora de ordem. A primeira alternativa corresponde a uma execução seqüencial do código, no qual as instruções são executadas e os resultados atualizados na mesma ordem de busca na memória. Nem mesmo os pipelines comuns (não superescalar) utilizam esta abordagem mas a mesma deve considerada para termos de comparação. Capítulo 2 – Arquiteturas SISD de alto desempenho 12 Para exemplificar esta alternativa, vamos considerar uma arquitetura superescalar de 2 vias, com 3 unidades funcionais, executando um trecho de código de 6 instruções que tem as seguintes restrições: I1 precisa de 2 ciclos para execução I3 e I4 utilizam a mesma unidade funcional I5 depende de I4 I5 e I6 utilizam a mesma unidade funcional O diagrama a seguir mostra a utilização dos diferentes estágios do pipeline em questão. Decodificação Execução Atualização Ciclo I1 I2 1 I3 I4 I1 I2 2 I3 I4 I1 3 I4 I3 I1 I2 4 I5 I6 I4 I3 5 I6 I5 I4 6 I6 I5 7 I6 8 A segunda alternativa de despacho prevê o término das instruções em uma ordem diferente da ordem de busca. Isto é comum em arquiteturas RISC, principalmente quando existem instruções do tipo multiciclo. A seguir é mostrado o diagrama do mesmo trecho de programa anterior com a possibilidade de término fora de ordem. Como visto na seção sobre pipelines multiciclo, o término fora de ordem torna possível o aparecimento de dependência do tipo WAW, também chamada de dependência de saída. Decodificação Execução Atualização Ciclo I1 I2 1 I3 I4 I1 I2 2 I4 I1 I3 I2 3 I5 I6 I4 I1 I3 4 I6 I5 I4 5 I6 I5 6 I6 7 A terceira alternativa compreende o despacho e o término fora de ordem. Para tornar esta abordagem possível, é preciso desacoplar os estágios de decodificação e execução e introduzir um novo elemento entre os mesmos, chamado de buffer de instruções (instruction window). Desta forma, tão logo as instruções sejam decodificadas, elas são enviadas para o buffer de instruções e o processador pode continuar a decodificar as instruções seguintes. Assim que a respectiva unidade funcional esteja disponível, a instrução presente no buffer pode ser despachada para execução. Qualquer instrução podeser despachada considerando que não haja dependência ou conflito com outras. O diagrama Capítulo 2 – Arquiteturas SISD de alto desempenho 13 de utilização do pipeline para este caso é visto a seguir. Decodificação Execução Atualização Ciclo I1 I2 1 I3 I4 I1 I2 2 I5 I6 I1 I3 I2 3 I6 I4 I1 I3 4 I5 I4 I6 5 I5 6 O resultado de um despacho fora de ordem é um processador com capacidade de antecipação de instruções. O buffer de instruções não é um estágio adicional do pipeline, significando apenas a capacidade que o processador tem de manter informações para o despacho de instruções. O despacho fora de ordem torna possível o aparecimento de dependências do tipo WAR, também chamadas de antidependências. O trecho de código a seguir é utilizado para exemplificar as dependências WAW e WAR. I1: R3 ¬ R3 op R5 I2: R4 ¬ R3 + 1 I3: R3 ¬ R5 + 1 I4: R7 ¬ R3 op R4 I2 depende de I1 (RAW) e não pode ser executada em paralelo. Da mesma forma I4 depende de I3 (RAW). Entre I1 e I3 não existe dependência de dados mas as duas instruções atualizam o mesmo registrador e não podem ser executadas em paralelo (WAW). Assim, a instrução I3 deve obrigatoriamente ser executada após I1. Além disso, apesar de I3 não possuir dependência de dados em relação à I2, I3 não pode atualizar o resultado antes de I2 ler os seus operandos, o que caracteriza uma antidependência (WAR). Renomeação de registradores (register renaming) Ao contrário das dependências do tipo RAW, as dependências do tipo WAW e WAR aparecem pela utilização dos mesmos registradores por instruções diferentes, o que é um conflito por armazenamento. Isto torna-se mais crítico quando técnicas de otimização de registradores são implementadas para maximizar o uso dos registradores. Uma forma de contornar este problema é chamada de renomeação de registradores, e consiste na alocação dinâmica dos registradores pelo hardware do processador para armazenamento temporário dos valores utilizados pelas instruções. Quando um novo valor para um registrador é criado, um registrador de rascunho é alocado para receber o mesmo. Instruções posteriores que utilizam este valor passam por um processo de renomeação de registrador, o qual garante a correção de resultados. No instante adequado, o registrador original é atualizado. A seguir é mostrado como ocorre o processo de renomeação, considerando o trecho de código acima. Capítulo 2 – Arquiteturas SISD de alto desempenho 14 I1: R3b ¬ R3a op R5a I2: R4b ¬ R3b + 1 I3: R3c ¬ R5a + 1 I4: R7b ¬ R3c op R4b Com a renomeação dos registradores, a instrução I3 pode ser executada em paralelo com a instrução I1. 2.6.3 Very Long Instruction Word (VLIW) Uma abordagem de execução paralela similar à abordagem superescalar foi sugerida antes desta, e compreende arquiteturas com instruções longas. Esta abordagem prevê que várias instruções sejam “empacotadas” em uma grande instrução e despachadas simultaneamente. Esta tecnologia está baseada no compilador que tem a responsabilidade de gerenciar as dependências e a utilização dos recursos de hardware. A grande vantagem de arquiteturas superescalares é a possibilidade de executar o código sem modificação, enquanto que arquiteturas VLIW precisam executar código específico.
Compartilhar