Paralelismo em Sistemas Microprocessados

Os primeiros processadores foram desenvolvidos para executar programas de maneira sequencial e uma instrução precisava ser executada completamente antes que outra instrução pudesse ser executada. Algum avanço no desempenho foi conseguido usando-se estratégias como o aumento a largura do barramento interno, memória caches e o aumento da frequência de clock. Neste artigo, trataremos de técnicas de projeto baseados no conceito de paralelismo. No próximo, expandiremos o assunto falando especificamente sobre arquiteturas vetoriais e GPUs.

Arquitetura Pipeline

Com a técnica do pipeline, várias instruções podem ser executadas em paralelo (ILP – Instruction-Level Parallelism). Embora a natureza sequencial de execução dos programas seja mantida, o pipeline permite que uma instrução comece a executar antes que instruções anteriores a esta completem sua execução.

arjona_art03_fig01

Figura 1 – Exemplo de arquitetura pipeline do MIPS. Este pipeline possui 5 estágios (Fetch, Decode, Execute, Memory Access e Write Back). (Fonte: [1])

O ciclo de processamento é quebrado em vários estágios e cada estágio executa uma instrução diferente no mesmo intervalo de tempo (ciclo de clock). O número de estágios define a profundidade de um pipeline e varia de acordo com o projeto. Em geral, quanto maior a profundidade de um pipeline, mais instruções são executadas em paralelo e maior pode ser a frequência de operação do circuito, pois o caminho de dados (datapath) é quebrado em unidades funcionais com atrasos de propagação menores (desde que devidamente balanceados). Entretanto, a latência total, que é a soma dos atrasos de cada estágio, pode aumentar.

Vídeo – Arquitetura pipeline versus multi ciclo. 

A latência no pipeline não chega a ser um problema, pois idealmente o número médio de instruções executadas por ciclo do processador (CPI) tende a 1 quando muitas instruções são executadas. Porém, há vários problemas associados ao pipeline que tendem a aumentar (piorar) o CPI como [1]:

– estrutura física (recursos disponíveis);
– dependência de dados;
– dependências de controle (instruções de desvio);
– interrupções/exceções.

Arquiteturas Superscalar e VLIW

Algumas técnicas permitiram expandir os limites de paralelismo no pipeline e executar mais de uma instrução por ciclo de clock (CPI < 1). A idéia básica consiste em replicar algumas unidades funcionais do datapath do pipeline para que alguns tipos de instruções, eventualmente, possam executar simultaneamente durante o mesmo ciclo de clock.

arjona_art03_fig02

Figura 2 – Na arquitetura Pipeline Superscalar vários blocos de execução executam em paralelo. Para lidar com as dependências o hardware armazena as instruções em buffers e o controle reordena as instruções para reduzir stalls.

Dois tipos de arquiteturas que utilizam este conceito são a VLIW (Very Long Instruction Word) e a Superscalar (Figura 2). Na primeira, o compilador é responsável por controlar as dependências e despachá-las. O compilador prevê que instruções podem ser rearranjadas de forma que possam ser emitidas na forma de uma única e grande instrução com diversas operações para serem executadas em paralelo. Já na arquitetura Superscalar é o processador o responsável pelo controle e ordenação das instruções, podendo o compilador ser utilizado como um facilitador.

Arquitetura Multithreading

Em um processador com Pipeline, VLIW ou Superscalar, conflitos causados por dependências e interrupções sempre vão acontecer, fazendo que o processador paralise (stall) a execução de algumas instruções na fila do pipeline até que os conflitos sejam resolvidos.

A arquitetura Multithreading (no contexto de Hardware [2]) permite aproveitar o tempo ocioso do processador durante ocorrência de stalls. Isso é possível graças ao conceito de Threads [3]. Um processo pode ser dividido em vários blocos capazes de executar independentemente, denominados threads. Como estes blocos compartilham o mesmo espaço de endereçamento e muitos recursos do mesmo processo, a troca de contexto é muito mais rápida que no caso de dois processos distintos. Quando uma instrução de um thread paralisa, outro thread é executado no lugar.

arjona_art03_fig03

Figura 3 – Arquitetura Multithread Pipeline Superscalar. Neste exemplo, tem-se 4 Threads executando em 2 unidades de execução em paralelo. (Fonte [4]).

Sistemas Multiprocessados e Processadores Multicore

Todas técnicas anteriores permitiram obter algum grau de paralelismo utilizando uma única unidade de processamento. E se usássemos dois ou mais processadores para executar nossos programas? Sistemas multiprocessados ampliam as capacidades de paralelismo, pois várias unidades de processamento executam simultaneamente.

arjona_art03_fig04

Figura 4 – Exemplo de processador Multicore com memória compartilhada.

Um sistema multiprocessado pode ser composto por vários computadores (ex: clusters [5]) ou por vários núcleos de processamento (cores) contidos no mesmo chip, denominados processadores multicore. Comparados aos processadores de núcleo simples, os processadores multicores podem obter maior desempenho utilizando frequências de clock mais baixas. Isso é outra grande vantagem, pois altas frequências aumentam o consumo e dificultam o projeto.

Com sistemas multiprocessados é possível executar diferentes programas totalmente em paralelo, bem como, executar um único programa (dividido em threads) em várias unidades de processamento. Com isso, pode-se aumentar o throughput (a quantidade de trabalho feito em um espaço de tempo) e quando executando um processo com várias threads, reduz-se o tempo de execução comparado a um processador simples na mesma frequência de operação.

Referências:

[1] Hennessy, John. L.; Patterson, David A. Organização e Projeto de Computadores, 4a Ed, 2014.
[2] Multithreading (computer architecture). Wikipedia.
[3] Processos e Threads. Aulas de Regina Borges de Araujo – UFSCar.
[4] 64-bit Multicore Delivers Simultaneous Multithreading. Eletronic Design.
[5] Cluster. Wikipedia.

Deixe um comentário