Make your own free website on Tripod.com
http://www.sun.com

http://www.intel.com

http://www.mips.com/

http://www.hardwaresecrets.com

http://cse.stanford.edu/class/sophomore-college/projects-00/risc/pipelining/

http://www.inf.ufrgs.br/~cabral/museu.html

http://www.clubedohardware.com.br/ppro.html

http://www.clubedohardware.com.br/opteron-2.html


arq-superescalar@bol.com.br
Mande-nos um e-mail!

Arquiteturas Superescalares
Daniel Lopes Sampaio e Marcos Henrique Braz



Histórico
Durante a década de 70, foram desenvolvidas importantes pesquisas envolvendo máquinas SIMD (Single-Instruction stream, Multiple-Data stream) para atender ao intenso volume de operações numéricas de aplicações científicas. Exemplo: ILLIAC IV.
As aplicações cientificas , geralmente codificadas na linguagem FORTRAN, lidam com grande volume de dados de entrada, usualmente estruturados em arrays. Esses elementos são lidados através de estruturas de controle do tipo loop.
Os processadores vetoriais do tipo SIMD explora esse tipo de organização dos dados a partir de seus inúmeros elementos de processamento. Um processador vetorial é capaz, a partir de uma única instrução (vetorial) de máquina, de processar o equivalente a múltiplas iterações de loop. Por exemplo, supondo que queremos somar uma constante de um registrador a todos os elementos de um array. Da maneira convencional, teríamos várias iterações de loop somando a constante com cada elemento do array, envolvendo vários ciclos de processamento. Com uma instrução vetorial essa operação pode ser feita em apenas um ciclo de máquina.
Essa estratégia de processamento reduz significativamente o número de instruções buscadas, decodificadas e interpretadas. Logo, o tempo de processamento torna-se menor do que o tempo requerido se a aplicação fosse executada na forma convencional.
Para se utilizar o poder computacional dos processadores vetoriais com eficiência, o compilador precisa localizar grandes aglomerados de dados no código que possa ser buscados e operados simultaneamente a partir de um mínimo de instruções vetoriais. Por isso, o programa necessita de um elevado grau de regularidade nas suas estruturas de dados e de controle. Este modelo de processamento nos limita a somente ter em execução concorrente as instruções do mesmo tipo. Por isso esta arquitetura atende uma restrita classe de aplicações: as aplicações que envolvem muitas operações aritmética. Essa limitação foi logo eliminada com a especificação de um modelo alternativo. Nesse modelo, diversas instruções, todas de uma mesma aplicação, podem ser executadas em paralelo, independente delas serem do mesmo tipo ou não. Por isso, além de atender uma classe mais ampla de aplicações, o modelo conserva as características de um processador de alto desempenho.



Visão Geral sobre Pipeline
Pipeline é uma técnica de implementação de processadores que permite a sobreposição temporal das diversas fases de execução de instruções. Há a técnica monociclo, mais simples, que executa uma instrução, exclusivamente, por vez. A técnica de pipeline é dividir o processo em estágios distintos, normalmente quatro ou seis, e processá-los de forma paralela (não processando dois estágios iguais ao mesmo tempo, obviamente).

Exemplo:

Um processador que tem suas instruções executadas em cinco estágios:

1.Busca da instrução na memória.

2.Leitura dos registradores enquanto a instrução é decodificada (estamos simulando um processador que permite que a leitura e a decodificação ocorram ao mesmo tempo).

3.Execução de uma operação ou cálculo de um endereço.

4.Acesso a um operando na memória.

5.Escrita do resultado em um registrador.


Em condições ideais, o ganho devido ao pipeline é igual ao número de estágios do pipe. No nosso caso acima, ele seria cinco vezes mais rápido que um processador similar que utilizasse a técnica de monociclo. Na prática, podemos perceber que o balanceamento não é tão preciso. É bom deixar claro que o pipeline melhora a performance aumentando o número de instruções executadas na unidade de tempo, e não por meio da diminuição do tempo de execução de uma instrução individual.



O Problema da Espera pelo Transcurso do Maior Tempo de Latência
O tempo de latência de uma operação é o intervalo de tempo requerido para a execução de uma operação. Esse tempo varia com a complexidade da operação. Exemplo: a latência de uma operação de multiplicação é maior que a latência de uma operação de soma, que é maior que a latência de uma operação de lógica.
Com o objetivo de simplificar o projeto dos processadores tipo RISC, o tempo de latência da instrução mais complexa é usado para determinar o ciclo de máquina. Ou seja, aumenta o tempo de processamento e a unidade de controle permanecerá ociosa após a execução de operações com latência menores.
No projeto de uma arquitetura Super Escalar, a espera pelo transcurso do maior tempo de latência deve ser evitada para não haver uma queda considerável no desempenho do hardware. Para garantir essa eficiência, o processador possui um complexo algoritmo de tratamento de latências.



Componentes de Uma Arquitetura Superescalar
Uma arquitetura superescalar deve possuir uma série de componentes especiais para executar mais de uma instrução por ciclo, que relacionamos a seguir:

  • Unidade de Busca de Instruções: capaz de buscar mais de uma instrução por ciclo. Possui também um preditor de desvios, que deve ter alta taxa de acerto, para poder buscar as instruções sem ter que esperar pelo resultados dos desvios.
  • Unidade de Decodificação: capaz de ler vários operandos do banco de registradores a cada ciclo. Note que cada instrução sendo decodificada pode ler até dois operandos do banco de registradores.
  • Unidades Funcionais Inteiras e de Ponto Flutuante: em número suficiente para executar as diversas instruções buscadas e decodificadas a cada ciclo.


  • Limitações de Uma Arquitetura Superescalar
    A abordagem superescalar depende da habilidade de executar várias instruções em paralelo. O termo paralelismo no nível de instruções diz respeito ao nível no qual as instruções de um programa podem ser executadas de forma paralela (em média).

    Limitações de uma estrutura superescalar:

  • Dependência de dados verdadeira
  • Dependẽncia de desvios
  • Dependência de recursos


  • Dependência de Dados Verdadeira – Considere a seguinte seqüência de instruções:

    add r1, r2 # carregar registrador r1 com a soma dos conteúdos de r1 e r2
    move r1, r3 # carregar registrador r3 com o conteúdo de r1


    A segunda instrução pode ser buscada e decodificada antecipadamente, mas não pode ser executada até que seja completada a execução da primeira instrução. A razão é que a segunda instrução requer dados produzidos pela primeira instrução. Essa situação é conhecida como dependência de dados verdadeira (também chamada dependência de fluxo ou dependência de escrita-leitura).

    Dependência de Desvios – A presença de desvios condicionais em uma seqüência de instruções complica a operação do pipeline. A instrução seguinte a um desvio condicional (tomado ou não) depende dessa instrução de desvio. Esse tipo de dependẽncia também afeta uma pipeline escalar, mas a conseqüência desse tipo de dependência é mais severa em uma pipeline superescalar, porque o número de instruções perdidas em cadea atraso é maior. Se forem usadas instruções de tamanho variável, surge ainda um outro tipo de dependência. Como o tamanho de uma instrução particular não é conhecido, uma instrução deve ser decodificada, pelo menos parcialmente, antes que a instrução seguinte possa ser buscada. Isso impede a busca simultânea de instruções, requerida em uma pipeline superescalar. Essa é uma das razões pelas quais técnicas supersescalares são mais diretamente aplicáveis a arquiteturas RISC ou do tipo RISC, que possuem instruções de tamanho fixo.

    Dependência de Recursos – Um conflito de recurso ocorre quando duas ou mais instruções competem, ao mesmo tempo, por um mesmo recurso. Exemplos de recursos incluem memórias, caches, barramentos, portas de bancos de registradores e unidades funcionais (por exemplo, o somador da ULA). Em termos de pipeline, um conflito de recurso apresenta um comportamento semelhante ao de uma dependẽncia de dados. existem, entretanto, algumas diferenças. Por um lado, conflitos de recursos podem ser superados pela duplicação de recursos, enquanto uma dependẽncia de dados não pode ser eliminada. Além disso, quando uma operação efetuada em uma dada unidade fucional consome muito tempo para ser completada, é possível minimizar os conflitos de uso dessa unidade por meio de sua implementação como uma pipeline.



    Visão Geral Sobre componentes Especiais
    Janela – É uma fila de instruções entre o estágio de decodificação¹ e o estágio de execução². As instruções aguardam nesta janela que os seus operandos fiquem prontos, quando os mesmos não puderem ser lidos do banco de registradores, por haver dependência direta com outras instruções em execução no pipeline.
    Unidades Funcionais – É necessário um número de unidades funcionais inteiras e de ponto flutuante em número suficiente para executar as diversas instruções buscadas e decodificadas a cada ciclo.
    Unidade de Leitura / Escrita – Unidade especial para enfileirar os pedidos de leitura ou escrita da memória. Para haver maior desempenho, verifica quais instruções podem ser executadas fora de ordem sem causar problemas de consistẽncia, caso ocorram exceções no acesso à memória ou em instruções precedentes no código do objeto.
    1 e 2: Estágios de uma instrução, necessários para utilização de pipelines.



    Banco de Registradores
    Normalmente o banco de registradores possui múltiplas portas de leitura e de escrita, para permitir o início e término de várias instruções a cada ciclo. Porém, a adição de um grande número de portas ocasiona um aumento no tempo de acesso aos registradores. Eventualmente, pode-se limitar o número de portas e arbitrar o acesso quanto o número de operandos a serem lidos/escritos naquele ciclo, se for maior que a capacidade do banco de registradores.



    Detecção de Paralelismo
    Podemos classificar as máquinas Super Escalares em duas classes: maquinas que implementam o algoritmo de detecção do paralelismo em hardware e a classe sem esse mecanismo de detecção.
    No primeiro caso, compete ao algoritmo a tarefa de determinar se um ou mais comandos podem ser executados em paralelo. Ele é denominado mecanismo de despacho. Este mecanismo combinado com um sofisticado esquema de decodificação viabilizam a exploração do paralelismo, logo, tornam as unidades de controle dessa arquitetura mais complexas. Independente da estruturação do código paralelo, o hardware tentará explorar ao máximo os recursos da máquina.

    Exemplos de máquinas desta classe:

  • CDC-6600
  • IBM-360/91
  • IBM RS/6000
  • Intel i960


  • Para permitir essa detecção, o algoritmo precisa ter acesso a um bloco de instruções máquina. Por isso há a necessidade de uma janela de instruções dentro do processador que armazena um bloco de instruções prontas para execução. Assim o algoritmo decide quais instruções serão executadas em paralelo.

    Na classe de arquiteturas que não implementam o algoritmo de detecção, seus respectivos programas precisam ser otimizados previamente para poder acionar os mecanismos de paralelismo. O procedimento de detecção das instruções que serão despachadas é semelhante aos passos de um algoritmo de compactação. Fica a encargo do compilador (ou otimizador) a tarefa de detectar e escalonar instruções que serão executadas simultaneamente.
    Portanto, a qualidade do código objeto desempenha um importante papel na taxa de unidades funcionais que estarão operando em paralelo durante a execução do código.

    Exemplos de máquinas desta classe:

  • Intel i860
  • máquinas VLIW


  • Máquinas VLIW (Very Long Instruction Word)
    Execução de múltiplas operações, escalonadas por “software”, concorrentemente

    Durante muitos anos, processadores com instruções horizontais têm sido utilizados na realização de sistemas dedicados a aplicações específicas, que requerem um intensivo volume de computação: aplicações com processamento de sinais.
    Neste tipo de máquina Super Escalar, a parte operacional consiste em diversas unidades funcionais conectadas a um banco global de registradores. Cada uma dessas unidades é controlada por um conjunto de bits da palavra de instrução. Em tempo de compilação, é especificado nas instruções de máquina qual operação será ativada na unidade funcional. Inclui também campos para especificar registradores fontes e destino. A partir de informações na instrução corrente, o seqüenciador determina o endereço da próxima instrução.

    Eis um esquema de uma arquitetura VLIW:

    Arquiteturas SMT
    SMT é uma técnica que permite múltiplas threads despacharem múltiplas instruções a cada ciclo para unidades funcionais de um processador superescalar. Este combina a capacidade de despacho de múltiplas instruções das arquiteturas superescalares, com a habilidade de esconder latência das arquiteturas multithreading. A cada instante de tempo, instruções de diferentes threads podem estar sendo executadas simultaneamente.
    Esta arquitetura busca reduzir o número de slots de despacho não ocupados a cada ciclo (elevado em arquiteturas multithreading) e o número de ciclos em que nenhuma instrução é despachada (elevado em arquiteturas superescalares).

    As arquiteturas SMT podem ser de três tipos básicos (Tullsen, ISCA95):

  • Full Simultaneous issue - Modelo ideal, mas de difícil realização, onde não há restrição sobre o número de instruções de cada thread que pode ser despachada a cada ciclo.
  • Limited Simultaneous Issue - Apenas um número limitado (1 a 4 tipicamente) de instruções de cada thread pode ser despachado a cada ciclo.
  • Limited Connection - Restringem o número de unidades funcionais de cada tipo que podem estar conectadas a cada contexto.


  • Casos de Uso