Arquitectura de Computadores

Notas de estudo

Alberto José Proença

1997/98

EM CONSTRUÇÃO... 

 

Índice geral

 Capítulos | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |

 

  1. O pipeline na arquitectura dum processador
    1. O datapath do MIPS sem pipeline
    2. Análise dos níveis de pipeline num processador (MIPS)
    3. Dependência de dados numa arquitectura com pipeline (MIPS)
    4. Dependência de controlo numa arquitectura com pipeline (MIPS)
    5. Análise de desempenho numa arquitectura com pipeline e com cache (MIPS)
    6. Análise comparativa de processadores comerciais

 

Analisou-se já a arquitectura interna dum CPU RISC - tomando como exemplo o MIPS - e respectivas implementações usando apenas um ciclo de clock para a execução de cada instrução, ou em ambiente multi-ciclo (resumo em 13.1). Introduz-se agora o ambiente encadeado de execução de instruções (uma forma de paralelismo de execução, ao nível da instrução: paralelismo temporal). Analisam-se em 13.2 as modificações a introduzir ao nível do datapath e da unidade de controlo, com estudo detalhado de um exemplo com uma sequência de instruções. Este assunto é tratado com detalhe no texto de apoio (ver 6.3).

Qualquer arquitectura com pipeline apresenta, no entanto, alguns problemas que podem ter resolução complexa, nomeadamente para garantirem um funcionamento correcto na ocorrência de inter-dependência entre instruções. Em 13.3 analisam-se os data hazards resultantes da dependência de dados (leitura de registos após a sua escrita em operações lógicas/aritméticas ou de acesso à memória), e as abordagens e implementações para a sua resolução. Este assunto é tratado com detalhe no texto de apoio (ver 6.4).

Em 13.4 analisam-se os control hazards resultantes da dependência de controlo (em instruções de salto condicional/incondicional, e em excepções/interrupções), e as abordagens e implementações para a sua resolução. Este assunto é tratado com detalhe no texto de apoio (ver 6.5 e 6.6).

Feito o estudo detalhado duma arquitectura de processador com 5 níveis de pipeline, e respectivas técnicas de implementação e melhoria da unidade de controlo para suporte a um determinado datapath (que implementa um subconjunto de instruções do MIPS), a secção 13.5 destina-se a apresentar um exemplo detalhado da execução dum programa, ciclo a ciclo do clock, consoante se vão considerando as várias estratégias de optimização no pipeline, e considerando ainda os conceitos adquiridos no Cap. 11 (organização de memória e cache). Em resumo, o exemplo cobre a matéria exposta na bibliografia de referência nos capítulos 6 e 7.

Em todos os capítulos apresentados até este ponto, a ênfase no modelo de referência foi sempre colocada numa versão simplificada dum processador comercial: a 1ª versão comercial do processador MIPS, com a designação de MIPS R2000. Para fins pedagógicos - e para melhor se entender muitos dos detalhes de implementação - optou-se ainda por uma versão simplificada dessa mesma arquitectura. Esta abordagem permitiu, de certa maneira, apresentar um modelo de referência para arquitecturas RISC que se adapta à grande maioria das arquitecturas actualmente existentes. Contudo, o tema da Arquitectura de Computadores não ficaria completo se não fosse feita alguma referência a processadores reais disponíveis no mercado: os processadores Alpha da Digital, Pentium da Intel, as novas linhas do MIPS, os PowerPC da IBM/Motorola/Apple, os SPARC da Sun, ...

Uma mera apresentação descritiva de cada uma das arquitecturas não iria certamente contribuir para a valorização/formação científica e, pior ainda, arriscava-se a tornar-se obsoleta ainda antes da conclusão da licenciatura por parte de cada uma dos potenciais interessados no assunto. Como alternativa, a metodologia adoptada para introduzir a tecnologia actual num contexto de auto-actualização foi a seguinte: identificar um conjunto de itens que permitem caracterizar e comparar as arquitecturas de processadores existentes ou em projecto, e apresentar alguns processadores à luz desse mapa comparativo. É este o modelo proposto em 13.6, fechando assim o capítulo.

 

  1. O datapath do MIPS sem pipeline
  2. fig 6.1

    Execução de instruções em pipeline

    fig 6.2

     

  3. Análise dos níveis de pipeline num processador (MIPS)

Nota: datapath equivalente ao da arquitectura de ciclo simples

1. Busca da instrução e incremento do PC/IP IF

2. Descodificação da instrução e selecção de registos ID

3. Execução: operação aritmética/lógica ou cálculo do endereço de memória ou teste de condição em instrução de salto Ex

4. Acesso à memória Mem

5. Escrita de resultado (da ALU ou da Mem) em registo WB

| IF |

| ID |

| Ex |

| Mem |

| WB |

fig 6.12

 

Exemplo de sequência de instruções (fig. 6.16 a 6.18):

lw $10, 9 ( $1 )

sub $11, $2, $3

 

fig 6.24

fig 6.22

1. Exemplo de sequência de instruções

lw $10, 9 ( $1 )

sub $11, $2, $3

and $12, $4, $5

or $13, $6, $7

add $14, $8, $9

2. Análise ciclo-a-ciclo (análise nível a nível de pipeline ; preparação dos valores a carregar no registo de pipeline no início do ciclo seguinte; ver fig. 6.25 a 6.29):

Ciclo 1: IF lw... Reg IF/ID: 32 (PC_lw+4) + 32 (<instr_lw>)

ID/Ex/Mem/WB ????

Ciclo 2: IF sub... Reg IF/ID: 32 (PC_sub+4) + 32 (<instr_sub>)

ID lw... Reg ID/Ex: 2 (WB; 11b) + 3 (Mem; 010b) +

4 (Ex; 0001b) + 32 (PC_lw+4) + 32 (<$1>) +

32 (<$10>) + 32 (Imm/rd; +9) + 5 (rt; 10)

Ex/Mem/WB ???

Ciclo 3: IF and... Reg IF/ID: 32 (PC_and+4) + 32 (<instr_and>)

ID sub... Reg ID/Ex: 2 (WB; 10b) + 3 (Mem; 000b) +

4 (Ex; 1100b) + 32 (PC_sub+4) + 32 (<$2>) +

32 (<$3>) + 32 (Imm/rd; 11) + 5 (rt; 3)

Ex lw... Reg Ex/Mem: 2 (WB; 11b) + 3 (Mem; 010b) +

32 (PC_lw+4) + 1 (Zero; 0) + 32 (ALUresult; <$1>+9) +

32 (<$10>) + 5 (rt; 10)

Mem/WB ??

Ciclo 4: IF or... Reg IF/ID: 32 (PC_or+4) + 32 (<instr_or>)

ID and... Reg ID/Ex: 2 (WB; 10b) + 3 (Mem; 000b) +

4 (Ex; 1100b) + 32 (PC_and+4) + 32 (<$4>) +

32 (<$5>) + 32 (Imm/rd; 12) + 5 (rt; 5)

Ex sub... Reg Ex/Mem: 2 (WB; 10b) + 3 (Mem; 000b) +

32 (PC_sub+4) + 1 (Zero;0) +32 (ALUresult; <$2-$3>)+

32 (<$3>) + 5 (rt; 10)

Mem lw... Reg Mem/WB: 2 (WB; 11b) + 32 (Mem[<$1>+9]) + 32 (ALUresult; <$1>+9) + 5 (rt; 10)

WB ?

Ciclo 5: ...

 

  1. Dependência de dados numa arquitectura com pipeline (MIPS)

fig 6.31

 

 

Condições de teste para detecção de data hazards

Ex-hazard: RegIF/ID(ReadReg1 / 2) = RegID/Ex(rt ou rd) Nota: para saber se rt ou rd usar RegDest

Mem-hazard:RegIF/ID(ReadReg1 / 2) = RegEx/Mem(WriteReg)

WB-hazard:RegIF/ID(ReadReg1 / 2) = RegMem/WB(WriteReg)

 

fig 6.32

 

fig 6.34

 

sub $2, $1, $3

and $4, $2, $5

or $8, $2, $6

add $9, $4, $2

slt $1, $6, $7

 

Data forwarding nas instruções do tipo-R

fig 6.41

Acrescentando uma unidade de forwarding

fig 6.42

 

Condições de teste para fazer data forwarding (instruções tipo-R)

Ex-hazard: RegEx/Mem(RegWrite) = 1 e RegID/Ex(ReadReg1 / 2) = RegEx/Mem(WriteReg) => ALUSelA / B = 01 Nota: RegID/Ex(ReadReg1 / 2) é novo

Mem-hazard: RegMem/WB(RegWrite) = 1 e RegID/Ex(ReadReg1 / 2) = RegMem/WB(WriteReg) => ALUSelA / B = 10

WB-hazard: não há, desde que a leitura do Reg se faça no mesmo ciclo, após a escrita

 

fig 6.44

 

fig 6.47

 

Ex-hazard: RegID/Ex (RegWrite) = 1 e RegID/Ex (RegDest) =

RegIF/ID(ReadReg1 / 2) = RegID/Ex(WriteReg)

=> stall

fig 6.48

 

  1. Dependência de controlo numa arquitectura com pipeline (MIPS)

- saltos condicionais

- saltos incondicionais

Exemplo

fig 6.50

1. Empatar o pipeline (stall)

fig 6.51

2. Previsão estática: o salto não ocorre

Condições para detectar que salta em beq:

[ RegEx/Mem(Branch) e RegEx/Mem(Zero) ] = 1

Acções: flush IF7ID, ID/Ex e Ex/Mem

fig 6.53

Exemplo (fig. 6.54)

3. Atrasar execução do salto (branch delay slot )

    1. Previsão dinâmica

 

E as instruções de jump ?

Causas de excepções/interrupções no MIPS

fig pag 344

Alterações ao MIPS para suportar arithmetic overflow

fig 6.55

Exemplo (fig. 6.56)

 

  1. Análise de desempenho numa arquitectura com pipeline e com cache (MIPS)

Considere o modelo de uma arquitectura RISC com o pipeline da fig. 6.24, sem forward unit, sem hazard detection unit, com write back na primeira metade do ciclo, com pipeline stall em instruções de salto e com cache "quente" e de dimensão infinita. Considere agora o seguinte programa em linguagem máquina simbólica, cujo ficheiro executável irá ser carregado na memória com início no endereço 0x8000.

mov $s1, $0

mov $s2, $0

mov $s0, -1024

sum: lw $t0, 0xC400($s0)

addu $s1, $s1, $t0

sw $s1, 0xE400($s0)

addu $s2, $s2, $s1

addiu $s0, $s0, +4

bne $s0, $0, sum

mov $s1, $0

 

a) Identifique todas as dependências de dados neste programa e introduza as instruções nop necessárias para que a execução do programa esteja correcta. Calcule o CPImin e o CPI efectivo, na execução deste programa neste processador. Comente os resultados.

Sugestão:

1.Analise o significado e consequência da não existência das unidades de forward e de hazard detection, bem como do facto de a operação dewrite back em registo ser efectuada na 1ª metade do ciclo, permitindo a leitura do conteúdo dos registos na 2ª metade; com base neste conhecimento, é possível calcular quantas instruções deverão estar entre 2 instruções com dependências críticas de dados (que no caso deste MIPS são as de RAW).

2. Analise o significado e consequência do pipeline stall em instruções de salto, i.e., da inserção de bolhas após a execução de qualquer instrução de salto (absoluto e relativo), logo após a sua descodificação; com base neste conhecimento, é possível calcular quantas bolhas são automaticamente inseridas por salto.

3. Considere uma cache "quente" aquela que já contém toda a informação que o programa necessita para a sua execução (neste caso o código do programa e a área dos dados); e se considerar ainda que ela tem dimensão infinita, então tem a certeza que toda essa informação coube na cache, e que nenhum acesso à cache de instruções ou de dados será penalizado no funcionamento do pipeline.

4. Conte agora o número de instruções x que são precisas executar para concluir o especificado.

5. Supondo que o pipeline estará sempre ocupado com tarefas úteis (modelo óptimo de arquitectura), verifique quantos ciclos de clock são precisos para completar a execução (devará dar mais 4 que o nº de instruções, devido à latência de execução da 1ª instrução); com base nos cálculos efectuados em 4. e 5. pode-se obter o CPImin - que deverá ser (x +4)/x .

6. Identifique todas as dependências de dados entre as instruções, e veja, instrução a instrução, quantas "bolhas" são inseridas, quer através da execução de nops gerados pelo compilador para resolução das dependências de dados, quer ainda inseridas pela unidade de controlo de saltos no hardware ; daqui pode contar e estimar o nº total de ciclos de clock para executar este programa; usando como nº total de instruções a ser executadas no processador o valor x calculado em 4. (que não é o correcto; porquê?), calcule agora o CPI efectivo.

 

b) Reordenando as instruções, reescreva o programa para minimizar o tempo de execução; calcule o tempo de execução do novo programa, em ciclos de clock. Compare com o valor obtido em a) e comente.

Sugestão: altere a ordem de execução de instruções de modo a remover ao máximo as dependências de dados; de notar que cada instrução que escreve num registo obriga à inserção de 2 nops caso a instrução que se lhe segue precise de ler o conteúdo desse registo; portanto, se se conseguir alterar a ordem de execução de instruções de modo a existirem 2 instruções sem dependência de dados após uma operação que escreve num registo, a utilização do pipeline é melhorada; apenas com a simples reordenação de instruções deve conseguir eliminar pelo menos 3 instruções de nop (com um truque adicional - e que não compromete evoluções da microarquitectura - poderá ainda eliminar mais um nop...).

 

c) Mostre o conteúdo do registo ID/Ex no início do 6º ciclo de clock.

Sugestão: identifique primeiro qual a instrução que no 5º ciclo se encontra no nível ID, sem se esquecer que na alínea anterior se conseguiu eliminar os nops no início do programa; agora consulte os apontamentos para construir essa instrução em binário e confirmar quais os sinais de controlo que a unidade de controlo gera nesse ciclo; o resto faz-se olhando apenas para a fig. 6.24.

 

d) Considere agora que o compilador usa a técnica de loop unroll (para além das melhorias introduzidas em b)). Use-a para processar 4 elementos de cada vez, e reescreva o código de modo a minimizar o tempo de execução. Calcule o tempo de execução do novo programa, em ciclos de clock. Compare com o valor obtido em b) e comente.

Sugestão:

1. A técnica de loop unroll serve essencialmente 2 objectivos: minimizar as penalizações resultantes das instruções de controlo de execução do ciclo,e espaçar mais as instruções que obrigam à inserção de "bolhas" no pipeline devido a dependências de dados.

2. Identifique as penalizações no funcionamento do pipeline resultantes das instruções de controlo de execução do ciclo (serão só as instruções de salto?...).

3. Reordene as instruções do novo corpo do ciclo - que processa agora 4x mais dados por cada iteração - usando, se necessário, mais registos (e verificando se dispõe do nº extra de registos que são precisos) e modificando eventualmente o próprio código do programa.

4. Use estas dicas na reescrita do código; se conseguir que cada instanciação do ciclo não tenha mais de 18 instruções úteis e 2 nops, então chegou a um resultado excelente!

 

e) Considere agora que a arquitectura possui forward unit e hazard detection unit. Modifique a solução obtida em b) e calcule o tempo de execução do novo programa, em ciclos de clock. Compare com os valores obtidos em b) e c) e comente.

Sugestão: lembre-se que a introdução da forward unit vai permitir eliminar as bolhas nas dependências de dados críticas que ocorrem após a execução de operações aritméticas/lógicas; contudo, nas operações de load continua a haver a necessidade de o compilador inserir um nop ; mas, se a arquitectura possuir uma hazard detection unit, é a própria unidade de controlo da arquitectura que se encarrega de introduzir uma bolha nesses casos de dependência crítica de dados, simplificando a tarefa de geração de código do compilador (mas não melhorando o desempenho na execução...)

 

f) Se o valor de CPI obtido nos programas resultantes da resolução de d) e de e) fossem iguais, que conclusões tiraria quanto ao desempenho do processador na execução deste programa? (Mesmo desempenho ou distinto, e porquê.)

Sugestão: lembre-se que a principal medida do desempenho do processador na execução deste programa é o tempo que ele necessita para o executar (em ciclos de clock), e um bom tempo não depende apenas de uma boa "máquina" - o processador - mas também de um bom "condutor" - o código gerado pelo compilador; com base nesta informação e na fórmula que nos relaciona o tempo de execução de um programa com os parâmetros da arquitectura, pode responder à questão...

 

g) Considere ainda a execução atrasada da instrução de salto, i.e., a arquitectura introduz um branch delay slot (para além dos melhoramentos já introduzidos na arquitectura em alíneas anteriores). Reescreva o código de modo a minimizar o tempo de execução e calcule esse tempo, em ciclos de clock. Compare com o valor mínimo obtido em a) e a melhor optimização que tinha conseguido em e), e comente.

Sugestão: por execução atrasada de uma instrução - de salto ou de load - entende-se que uma instrução só é efectivamente executada após a instrução que a segue; no caso da instrução de salto, isto significa que, quer o salto se concretize ou não, a instrução que se encontra na palavra seguinte da memória de instruções é sempre carregada e executada; como consequência para este processador, verifica-se que, em vez da arquitectura inserir 3 bolhas após a descodificação de um branch (ou 1 bolha após um jump), a unidade de controlo deixa executar a instrução que está imediatamente a seguir e apenas introduz 2 bolhas (no caso dum branch, e 0 no caso dum jump)

 

h) Considere ainda uma nova optimização da arquitectura relativamente a g): uma previsão estática de saltos - nunca salta. Reescreva o código de modo a minimizar o tempo de execução e calcule esse tempo, em ciclos de clock.

Sugestão: mesmo com branch delay slot cada instrução de salto condicional pode ainda desperdiçar 2 instruções (bolhas) quando a previsão estática falha; mas com saltos incondicionais isto já não acontece; estas dicas servem para alguma coisa?

 

i) Considere agora como alternativa a h) uma previsão dinâmica de saltos (com 1 bit): se da vez anterior saltou, também salta agora e para o mesmo endereço, se não saltou, também não salta. Reescreva o código de modo a minimizar o tempo de execução e calcule esse tempo, em ciclos de clock. Compare com o valor obtido em h) e comente.

 

j) Considere agora a versão optimizada do pipeline conforme descrita em h), mas com a seguinte hierarquia de memória: cache (I+D) de mapeamento directo, com 128 linhas de 4 palavras cada, com tempo de acesso à memória para leitura de 12 ciclos de clock, e com um barramento de 32 bits para aceder à memória. Considere ainda que a unidade de controlo está preparada para empatar o pipeline sempre que ocorre um miss, e que a estratégia de escrita na memória é de write back. Calcule o hit rate da cache e o novo valor do tempo de execução do programa proposto em h). Compare com o valor obtido em h) e comente.

Sugestão:

1. Leia com muita atenção este enunciado, e explicite todos os pressupostos que considere e que não tenham sido explicitados no enunciado, de preferência numa versão menos optimizada; por ex., considere que sempre que ocorrer um miss na leitura ou escrita, é preciso esperar que a linha toda seja lida da memória antes de o CPU poder aceder a uma palavra dessa linha .

2. Considere também que a linha da cache que está a substituir não precisa de ser escrita na memória, ou que, se precisar, não existe penalização temporal por tal.

3. Não se esqueça que cada vez que tem de ir à memória ir buscar uma linha da cache, isso é uma operação que contém 4 acessos à memória na arquitectura deste problema.

4. Faça um mapa da cache e verifique ainda em que linhas se encontram as instruções e os dados, uma vez que está a trabalhar com memória de mapeamento directo; isto não sugere nada?

5. No cálculo do hit rate não se esqueça de contabilizar todos os acessos à hierarquia de memória que o CPU tem de efectuar, quer para ir buscar as instruções, quer para ler ou escrever dados.

 

l) Apresente propostas distintas e complementares para: melhorar a latência, e a largura de banda no acesso à memória. Calcule, para a proposta com maior impacto no desempenho, o novo valor do tempo de execução do programa proposto em h). Compare com os valores obtidos em h) e j) e comente.

 

 

  1. Análise comparativa de processadores comerciais

Algumas sugestões de referências em revistas, para complemento desta matéria são apresentadas de seguida. Existem contudo excelentes locais na Internet com apontadores actualizados para as novidades em arquitecturas de processadores - para além das páginas dos fabricantes de chips (por ex., em digital.com, hp.com, ibm.com, intel.com, mips.com, motorola.com, ti.com, ...) - sendo de recomendar a "WWW Computer Architecture Home Page" (http://www.cs.wisc.edu/~arch/www/) e o "CPU Info Center" (http://infopad.eecs.berkeley.edu/CIC/).

 

Descrições de arquitecturas comerciais

Alpert, D., ..., Architecture of the Pentium Microprocessor, IEEE Micro, June 1993

Asprey, T., ..., Performance Features of the PA7100 Microprocessor, IEEE Micro, June 1993

Becker, M.C., ..., The PowerPC 601 Microprocessor, IEEE Micro, October 1993

Burgess, B., ... The PowerPC 603 Microprocessor, Comm.ACM, Vol.37, Nº6, June 1994

Kumar, A., ... The HP PA-8000 RISC CPU, IEEE Micro, March/April 1997

McLellan, E. The Alpha AXP Architecture and 21064 Processor, IEEE Micro, June 1993

Mirapuri, S., ..., The MIPS R4000 Processor, IEEE Micro, April 1992

O'Connor, J.M., ... picoJava-I: The Java Virtual Machine in Hardware, IEEE Micro, March/April 1997

Song, S.P., ... The PowerPC 604 RISC Microprocessor, IEEE Micro, October 1994

Thomson, T. ...,PowerPC 620 Soars, Byte, November 1994

Tremblay, M., ..., UltraSparc I: A Four-Issue Processor Supporting Multimedia, IEEE Micro, April 1996

Wayner, P., SPARC Strikes Back, Byte, November 1994

Yeager, K.C., The MIPS R10000 Superscalar Microprocessor, IEEE Micro, April 1996

 

Estudos comparativos

Smith, J.E., ... PowerPC 601 and Alpha 21064: A Tale of Two RISCs, IEEE Computer, June 1994

 

Artigos avançados

Smith, J.E., ... The Microarchitecture of Superscalar Processors, Proc.IEEE, Vol.83, nº12, December 1995

Hwu, W-M. W., ... Compiler Technology for Future Microprocessors, Proc.IEEE, Vol.83, Nº12, December 1995

 

Características gerais

Pipeline de instruções

Organização de memória

Processadores a comparar: Digital Alpha, Intel Pentium, MIPS Motorola PowerPC, SPARC, ...

 

Características gerais

Processor name / model / version / manufacturer

Ship date

Clock frequency

Instruction (size, formats, nº operands/arithm instr)

Harvard architecture (internal, external)

Data bus (nº x dim) (int reg - funct unit, fp reg - funct unit, data reg - cache, instr reg - cache, L1 cache - L2 cache, cache -ext)

Addressable memory (virtual (arch/implemented), physical)

Memory addressing modes (direct (size), reg, reg+offset (size), other)

Integer unit (nº reg x size, reg organisation, division (nº cycles))

Floating point unit (nº reg x size, standards)

Best performance (estimated/real) (clock/cache dim, SPECint, SPECfp)

 

Instruction pipeline

Pipeline stages (latency F-D-Ex-WB, min latency/instr type)

Pipeline Ex units (levels/latency) (integ, fp, mem i/f, branch, other)

Instruction level paralelism (only in Ex unit(nº), issue (nº), instr mix, dynamic control)

Data dependencies (delayed load, data forward, dynamic scheduling)

Branch dependencies (delayed branch, static prediction, dynamic predict)

Interrupts (multiple, precise)

 

Memory organisation

Pre-fetch buffers (instructions, data)

TLB (blocks x bytes) (instructions, data)

L1 cache (I+D / global, size (lines x words), placement policy, replacement policy, write policy, time (hit/penalty))

L2 cache (internal/external, I+D / global, size (lines x words), placement policy, replacement policy, write policy, time (hit/penalty))

Cache coherence protocol (multiprocessing)

Shared memory support (signals, instructions)