# Programação Paralela em Arquiteturas Multi-Core/Arquitetura Intel Core e Core 2

A microarquitetura Intel Core, divulgada em 2006 pela Intel, é uma nova arquitetura que permite um aumento de desempenho combinado à um menor consumo de energia. Possui recursos avançados que permitem um melhor desempenho por Watt. Dentre estes recursos temos uma execução mais rápida de instruções maiores, uma melhora no sistema de consumo de energia que possibilita a desativação temporária de áreas ociosas, um sistema aprimorado de predição de instruções e dados e também algumas novas instruções multimídia.
O texto abaixo apresenta em linhas gerais essa nova arquitetura e seus principais recursos.

### Introdução

Os processadores que têm sido desenvolvidos recentemente buscam em sua maioria alcançar o máximo de paralelismo possível. Essa afirmação pode ser verificada facilmente ao se analisar arquiteturas de processadores como os Sun Niagara, Sun Niagara 2 e o IBM/STI Cell.
Para alcançar uma maior eficiência em aplicações que exigem maior grau de paralelismo, a tendência atual é que os novos processadores contenham um número cada vez maior de unidades de processamento. Para produzir processadores com tantas unidades de processamento, é necessário diminuir a complexidade de cada unidade de forma a permitir que a produção do processador seja economicamente viável para o fabricante. Essa redução de complexidade pode afetar recursos que antes eram tidos como necessários nos processadores modernos, como a execução fora de ordem, utilizada para aumentar o número de instruções realizadas em um ciclo de clock.
Neste contexto temos a introdução de processadores baseados na microarquitetura Core da Intel, que busca aperfeiçoar ainda mais os complexos recursos existentes nos processadores modernos e ao mesmo tempo atacar o problema do processamento de aplicações paralelas acrescentando vários núcleos de processamento a um único processador.

#### Conceito de desempenho

O desempenho de um processador não pode ser medido apenas como uma proporção direta da frequência do relógio do processador, ou mesmo como a quantidade de instruções realizadas por ciclo do processador (IPC). O desempenho é dado pela simples equação:
Desempenho = Frequência $x$ IPC
Desta forma temos duas maneiras principais de aumentar o desempenho de um processador, aumentando a frequência ou o throughput. Assim, o aumento da capacidade de processamento depende da microarquitetura do processador e do aumento da frequência, ambos dependentes de como o processador é projetado e construído.

### Arquitetura

A tendência atual dos processadores voltados para ambientes paralelos é não implementar execução de instruções fora de ordem. A execução fora de ordem permite que uma seqüência de instruções enviadas para o processador sejam processadas internamente em uma ordem diferente da seqüência original, que busca aumentar o número de instruções processadas de acordo com a arquitetura do processador, ordenando novamente na seqüência original após o término da execução. Processadores que não contam com esse recurso precisam que o ordenamento das instruções seja feito antes de enviadas para o processador, através de otimizações feitas por um compilador, por exemplo.
A arquitetura Core foge à regra e busca aperfeiçoar as técnicas já existentes. Assim, cada núcleo de processamento é altamente eficiente e ao mesmo tempo complexo, dificultando a criação de processadores que possuam muitos núcleos. Espera-se que ganhos expressivos de poder de processamento sejam alcançados com a adição de novos núcleos de processamento aos processadores, ao contrário da estratégia anterior da Intel com a arquitetura NetBurst, onde os ganhos eram alcançados principalmente com avanço das técnicas de fabricação que permitissem que os processadores funcionassem a frequências cada vez maiores.
Abaixo encontra-se um diagrama simplificado de um núcleo de processamento (core) baseado na arquitetura Intel Core:
O dito popular que a Intel parece ter seguido ao desenvolve a arquitetura Core foi "Mais é Melhor". A arquitetura Core possui uma quantidade maior de cada unidade ou recurso que pode ser encontrada em uma unidade de processamento. A arquitetura Core possui mais lógica de decodificação, melhor reordenação de instruções, mais estações de reserva, mais hardware de execução, maiores buffer's e outros recursos encontrados nos mais de 150 milhões de transistores de cada processador baseado na arquitetura Core.
Apesar da adição de mais recursos à arquitetura Core, existem limites ao número de instruções que podem ser executados simultaneamente em um núcleo de processamento. Quanto maior o número de instruções a unidade de execução do núcleo pode processar simultaneamente, maior a dificuldade em manter a unidade de execução completamente ocupada, pois as instruções em execução não podem possuir dependências entre sí. Se várias instruções que possuem interdependências são enviadas à unidade de execução, apenas uma é executada enquanto as outras aguardam o término da primeira. Além disso, a latência do acesso à memória pode fazer com que a unidade de execução fique ociosa aguardando instruções e dados.
A arquitetura Core possui várias funcionalidades e soluções que visam manter a poderosa unidade de execução ocupada. Essas funcionalidades buscam principalmente minimizar o envio simultâneo de instruções que possuam dependência para a unidade de execução e minimizam o número de acessos à memória.
A Intel atribuiu nomes a cada uma dessas soluções, que são explicadas em maiores detalhes nas seções a seguir.

#### Intel Wide Dynamic Execution

A Execução Dinâmica é uma combinação de técnicas como a análise do fluxo de dados, execução especulativa, execução fora de ordem e tecnologia superescalar onde se tem mais de uma unidade de execução. A primeira vez que esta tecnologia foi usada pela Intel foi na microarquitetura Intel de 6ª geração, conhecida como P6, usada nos processadores Pentium Pro, Pentium II, and Pentium III. Para a microarquitetura Intel NetBurst, foi introduzido o Advanced Dynamic Execution, um dispositivo de execução especulativa proposto para manter a continuidade da execução de instruções dentro do processador. Além disso, a NetBurst possui um algoritmo de previsão de desvio (branch-prediction) mais eficaz diminuindo o número de reconfigurações do pipeline.
Com a microarquitetura Intel Core tem-se um ganho significativo da capacidade de despachar execuções devido ao Intel Wide Dynamic Execution. Essa tecnologia possibilita uma maior entrega de instruções por ciclos de clock melhorando tanto o tempo de execução como a utilização eficaz de energia. Cada núcleo de execução é, digamos, mais largo, possibilitando que cada núcleo busque, despache, execute e retorne até quatro instruções completas simultaneamente. Anteriormente a NetBurst podia trabalhar com ate três instruções por tempo, um ganho de desempenho de 33%. Outras melhorias incluem um melhor algoritmo de previsão de desvio, buffers de instruções maiores o que possibilita mais flexibilidade na execução além de outras melhorias que reduzem o tempo de execução.

##### Macrofusion©

Macrofusion é uma nova característica da nova arquitetura que permite reduzir o tempo de execução. Nas gerações anteriores cada instrução era decodificada individualmente e então executada. Com a Macrofusion permite-se que pares de instruções comuns, por exemplo, uma comparação seguida de um desvio condicional, sejam combinadas em uma única instrução interna (micro-op) durante a decodificação. Assim duas instruções do programa podem ser executadas como um único micro-op, reduzindo o trabalho total que o processador deveria realizar. Esta propriedade aumenta o número de instruções executadas por unidade de tempo ou reduz o tempo necessário para se executar certo conjunto de instruções. A conclusão direta é que a Macrofusion possibilita uma melhor resposta do processador com menos gasto de energia.
Para facilitar a Macrofusion uma nova e aprimorada unidade lógica e aritmética (ALU) foi desenvolvida para a microarquitetura Core. Esta nova ALU executa instruções combinadas pela Macrofusion em um único ciclo de clock.
A microarquitetura Intel Core também aprimorou a técnica de fusão de micro-op utilizado pela primeira vez na linha Pentium M. Essa técnica visa uma melhor utilização da energia do processador. Nos modernos processadores as instruções x86 dos programas, chamadas macro-op, são desdobradas em unidades menores de execução, os micro-ops, antes de serem despachados ao pipeline para o processamento. Esta fusão de micro-op é realizada nos micro operadores que possuem o mesmo macro-op para reduzir o número de instruções que realmente serão executadas. Isso possibilita um melhor escalonamento de instruções aumentando o throughput da máquina. Alguns estudos mostram que a fusão destes operadores pode reduzir em mais de 10% o número de micro-ops manipulados pela lógica do processador.

#### Intel Intelligent Power Capability

Intel Intelligent Power Capability foi desenvolvido, basicamente, para reduzir o consumo de energia e temperatura do processador. Esta inovação gerencia o consumo de energia em tempo de execução nos núcleos ativos. O resultado é a uma otimização na relação desempenho/consumo em todas as esferas de computação.
Para fazer isso, a microarquitetura Core possui aprimoramentos em recursos já existentes em processadores anteriores da Intel e alguns novos recursos;
Recursos de famílias anteriores:
* Intel Speedstep: A tecnologia Intel Speedstep permite que a frequência de operação (através da alteração de razão entre FSB e clock) e a tensão do núcleo de um processador sejam alterados em tempo de execução. Alguns fatores que podem levar à alteração da frequência e tensão são a fonte de energia do sistema (bateria ou fonte), estado térmico do processador. Outro fator importante é a política de gerenciamento de energia do sistema operacional, que pode selecionar o nível de economia de energia baseando-se, por exemplo, na utilização do processador.
* Enhanced Intel Speedstep: Todas as vezes que ocorre uma variação na frequência do processador, este fica indisponível por um curto período de tempo, enquanto que a variação na tensão do núcleo do processador não ocasiona esta indisponibilidade. O enhanced Speedstep permite que a tensão varie independentemente da frequência do processador (no Intel Speedstep a variação de tensão e frequência sempre ocorria em conjunto). Esta alteração melhora a disponibilidade do processador ao permitir que seu consumo seja reduzido sem a necessidade de alterar sua frequência
* Enhanced Halt State (Estado C1E): O processador entra no estado C1E (estado econômico de energia) quando o sistema operacional envia um comando HALT. Nos sistemas operacionais atuais este comando é enviado quando o sistema não encontra-se com carga máxima de utilização. Quando está no estado C1E a frequência do processador é alterada para o mínimo (através da alteração do multiplicador) além da tensão também ser reduzida.
Novos Recursos:
* Desabilitação seletiva de subsistemas: Processadores baseados na microarquitetura Core podem desabilitar unidades internas que não estejam sendo utilizadas. Essas unidades não são o núcleo inteiro, mas subsistemas como a ALU (unidade lógico-aritmética) e barramentos internos, que agora podem ser alimentados separadamente. A grande dificuldade nas implementações anteriores desse recurso é que ao alimentar novamente as unidades é necessário aguardar um curto período de tempo até que elas estejam novamente prontas para utilização. A implementação da Intel não aumenta o tempo de resposta ao religar unidades que não estavam em uso.
* Medição distribuída de temperatura: Por causa do novo recurso de desabilitação seletiva de subsistemas, partes diferentes do processador poderão estar ligadas/desligadas dependendo da utilização do sistema, fazendo com que as temperaturas no processador variem de maneira não uniforme. Com essa dificuldade em se medir a temperatura do processador eficazmente, a Intel distribuiu vários sensores de temperatura pelo processador. A temperatura informada para o sistema/usuário e maior temperatura encontrada dentre as medições de todos os sensores de temperatura do processador.

#### Intel Advanced Smart Cache

A arquitetura Intel Core foi desenvolvida desde o começo prevendo-se o suporte a vários núcleos por processador. Diferentemente dos processadores anteriores, os processadores Intel Core com múltiplos núcleos compartilham a memória cache de nível 2 (L2).
A primeira vantagem da estratégia de compartilhar o cache L2 é que a quantidade de cache L2 pode ser alterada dinamicamente de acordo com a carga dos núcleos. Em um processador DualCore, quando um núcleo está inativo, o núcleo ativo fica com toda a cache L2 à sua disposição. Quando vários núcleos estão ativos a cache L2 é dividia proporcionalmente entre os núcleos de acordo com a frequência de requisições feitas por cada núcleo à memória.
A segunda vantagem é que ao utilizar uma única cache L2 não é necessário utilizar técnicas para garantir a consistência de dados entre as caches dos vários núcleos, diminuindo a utilização do barramento entre o processador e a memória do sistema.
Uma terceira vantagem é que o espaço total disponível em cache L2 é melhor utilizado já que quando dois núcleos utilizam os mesmos dados eles não são duplicados em várias caches, sendo compartilhados pelos dois núcleos.
A última vantagem é que a microarquitetura Core possui lógica de controle adicional para permitir que os dados da cache L1 de um núcleo sejam transferidos para a cache L1 de outro núcleo passando pela cache L2 compartilhada. Isso permite um passo a menos (não é necessário transferir dados entre as caches L2 de cada núcleo) no compartilhamento de dados entre as caches L1 de diversos núcleos, potencialmente melhorando a performance do sistema quando vários núcleos executam a mesma tarefa.

#### Intel Smart Memory Access

Intel Smart Memory Access é o nome de um conjunto de técnicas utilizada para aumentar a performance do sistema de acesso à memória do processador. Consiste das técnicas de Pré-Carregamento e Desambiguação de Memória.

##### Pré-carregamento

A primeira técnica utilizada para aumentar a performance é o pré-carregamentode instruções e dados.
A microarquitetura possui 6 unidades independentes de pré-carregamento de dados:
* 2 unidades na cache de primeiro nível (L1) do primeiro núcleo
* 2 unidades na cache de primeiro nível (L1) do segundo núcleo
* 2 unidades na cache de segundo nível (L2) compartilhada entre os núcleos
A microarquitetura Core possui também 2 unidades independentes de pré carregamento de instruções:
* 1 unidade na cache de primeiro nível (L1) do primeiro núcleo
* 1 unidade na cache de primeiro nível (L1) do segundo núcleo
As unidades guardam informações sobre os padrões de acesso das unidades de execução aos dados e padrões de execução do programa. Alguns desses padrões de acesso são:
* Assumir se um desvio condicional provavelmente será tomado, baseado na probabilidade da instrução de desvio condicional alterar o fluxo de execução do programa de acordo com o histórico recente dos resultados deste desvio condicional específico. Quando o processador assume que o desvio será tomado, ele encontra o endereço de destino do desvio e começa a executar as instruções do novo local.
* Em um loop, os preditores de desvio normalmente assumem que na próxima iteração a execução ocorrerá dentro do loop (a condição para saída do loop é considerada sempre como não verdadeira). Sendo assim, esse preditores de desvio sempre erram a previsão na iteração que sai do loop. A microarquitetura Core introduziu preditores que registram em qual iteração um loop foi interrompido. Na próxima vez que o mesmo loop for executado, se o número de iterações antes de sair do loop for o mesmo, o preditor irá acertar a previsão da última iteração, prevendo-a como uma saída do loop
* Desvios condicionais indiretos (onde o endereço de destino é carregado de um registrador) são intrinsecamente difíceis de pré-carregar, já que a informação sobre o endereço de destino está indisponível durante o processo de predição. Quando os preditores assumem que um desvio condicional indireto será tomado, eles verificam em uma tabela se o desvio condicional indireto já foi tomado anteriormente e qual foi o seu endereço de destino naquela execução. Os preditores utilizam então esse endereço como o provável destino da execução atual.

##### Desambiguação de memória

Os processadores modernos utilizam a execução fora de ordem; uma técnica que altera a ordem em que as instruções são realizadas para permitir que um número maior de instruções esteja em execução em um determinado momento.
Quando ocorre uma instrução STORE seguida de um LOAD, podem acontecer duas situações:
* O LOAD vai tentar carregar o dado que foi salvo pelo STORE, sendo assim a ordem de execução das instruções não pode ser alterada.
* O LOAD vai carregar um dado diferente do salvo pelo STORE, sendo assim ele pode ser executado antes do STORE
O problema é que para diferenciar os dois casos, é necessário saber os endereços de memória onde o STORE está salvando os dados. Este endereço só fica disponível alguns ciclos após o início da execução do STORE. Como conseqüência, o processador deve aguardar um ciclo após o início da execução do STORE para decidir se o LOAD já pode começar a ser executado (em paralelo com o STORE) ou se o seu início deve ser postergado para depois da finalização da execução do STORE.
Estudos indicam que em mais de 97% dos casos não existe dependência entre os dados de STORE e LOAD consecutivos. Isso quer dizer que o LOAD poderia até ser executado antes do STORE.
Como resultado, uma instrução ADD após o LOAD-STORE, por exemplo, é executada em 5 ciclos (STORE -> define endereço -> LOAD-> espera load -> ADD), enquanto poderia ter sido executada em 3 ciclos (LOAD -> STORE / espera load -> ADD).
Para solucionar o problema, a microarquitetura Core possui algoritmos que determinam com uma grande probabilidade se um par de instruções STORE-LOAD está operando sobre os mesmos dados, sem a necessidade de aguardar a definição dos endereços de memórias que as instruções estariam acessando.
Vamos verificar como exemplo da desambiguação de memória o que acontece para a seguinte seqüência de instruções:
* 'STORE 13 REF' - Guardar o valor 13 na posição REF da memória.
* 'LOAD REF A' - Carregar o conteúdo da posição REF da memória no registrador A.
* 'ADD A, B, C' - Somar os registradores A e B, atribuindo o resultado ao registrador C.
No exemplo existem duas posições de memória, uma representada pelo quadrado vermelho e outra representada pelo quadrado azul. O sombreamento saindo dos quadrados indica que a instrução acessando aquele endereço de memória ainda não finalizou. Cada linha cinza representa um ciclo de execução do processador.
* Caso A: Nesse caso o LOAD vai carregar no registrador A as informações salvas na posição de memória vermelho pelo STORE, sendo assim ele fica impedido de iniciar sua execução até que o STORE seja finalizado.
* Caso B: Nesse caso o LOAD e o STORE estão trabalhando com posições de memória diferentes. Como esta independência só é descoberta após o ciclo de decodificação do STORE, a única alternativa possível é iniciar a execução do LOAD após o ciclo de decodificação do STORE. Este é o funcionamento das arquiteturas Intel anteriores à arquitetura Core.
* Caso C: Este caso ilustra o funcionamento da Desambiguação de Memória da arquitetura Core para a situação descrita no Caso B. O LOAD e o STORE estão trabalhando com posições de memória diferentes, mas através dos algoritmos de Desambiguação de Memória a independência é descoberta antes do STORE iniciar sua execução. Sendo assim, existe a alternativa de executar o LOAD antes do STORE. Nesse caso o LOAD termina sua execução mais cedo, permitindo que o ADD dependente do LOAD (ambos acessam o registrador A) também seja executado antes.

#### Intel Advanced Digital Media Boost

O Intel Advanced Digital Media Boost é um recurso que melhora significativamente a performance quando executa instruções SSE. Tanto as operações de ponto de flutuação com dupla precisão da SIMD em 128-bits como as operações aritméticas de inteiros SIMD em 128-bits reduzem o número total de instruções necessárias para executar uma determinada tarefa do programa, e como resultado pode contribuir para um aumento total da performance. Eles aceleram uma grande quantidade de aplicações, incluindo vídeo, som, imagem, processamento de fotos, encriptação, financeiras, científicas e de engenharia. As instruções de SSE intensificam a arquitetura da Intel ao permitir que os programadores desenvolvam algoritmos que podem misturar pacotes de pontos de flutuação de precisão individual com inteiros, usando tanto as instruções SSE como as instruções MMX, respectivamente.
Em várias das antigas gerações de processadores, as instruções SSE, SSE2 e SSE3 em 128 bits eram executadas em um nível sustentado de uma instrução completa a cada dois ciclos de relógio—por exemplo, a mais baixa em 64 bits em um ciclo e a mais alta em 64 bits no próximo ciclo. O recurso Intel Advanced Digital Media Boost permite que estas instruções em 128-bits sejam completamente executadas em um nível de rendimento de uma por ciclo de relógio, efetivamente dobrando a velocidade da execução para estas instruções. Isto aumenta ainda mais a eficiência total da Microarquitetura Intel® Core™ através do aumento do número de instruções controladas por ciclo. O recurso Intel Advanced Digital Media Boost é particularmente útil para a execução de importantes operações de multimídia envolvendo gráficos, vídeo e áudio e para o processamento de outros conjuntos de dados ricos que utilizam instruções SSE, SSE2, e SSE3.

## Referências

* ↑ Do Estrangeirismo Out of order execution - OOO
* ↑ Também conhecido pelo estrangeirismo performance
* ↑ Também conhecido pelo estrangeirismo prefetch
* ↑ Também conhecido pelo estrangeirismo Memory disambiguation
* ↑ Também conhecido pelo estrangeirismo prefetch
* ↑ Também conhecido pelo estrangeirismo branch
* ↑ Também conhecidos pelo estrangeirismo branch predictors
* ↑ S. Sethumadhavan, et al. Scalable Hardware Memory Disambiguation for High ILP Processors. In 36th Annual International Symposium on Microarchitecture, 2003.
* Inside Intel® Core™ Microarchitecture. Melhor texto introdutório sobre a Arquitetura
* Página da Intel sobre multicore. Um bom tópico introdutório
* Uma intrudução ao multicore Intel. Clube do Hardware
* Uma excelente apresentação com animações e textos explicativos da Intel. ( Em Ingles)
* Intel vs. AMD Gaming Benchmarks
* Um bom texto sobre a arquitetura Multicore Intel e do Athlon X2
* Benchmarks Avaliados pelo Tom's Hardware
* Novas Instruções Intel
* Intel Core WhitePaper
* Making the Move to Quad-Core and Beyond
* Inside Intel® Core Microarchitecture and Smart Memory Access
* Setting New Standards for Energy-Efficient Performance

### Referências por tópicos

* INTRODUÇÃO
** Inside Intel® Core™ Microarchitecture. Melhor texto introdutório sobre a Arquitetura
* Intel Wide Dynamic Execution
** Por Dentro da Microarquitetura Intel Core Unidades de Execução
** Evolution of the multi-core processor architecture Intel Core: Conroe, Kentsfield...
* Intel Intelligent Power Capability
** Energy-Efficient Performance
* Intel Advanced Smart Cache
** Dentro da Microarquitetura Intel® Core
** Cache de Memória e Unidade de Busca
** Getting Ready to Meet Intel Core 2 Duo: Página 6
* Smart Memory Access
** Cache de Memória e Unidade de Busca
** Inside Intel® Core™ Microarchitecture and Smart Memory Access
** Cache de Memória e Unidade de Busca
** Getting Ready to Meet Intel Core 2 Duo: Página 7
* Intel Advanced Digital Media Boost
** Extending the World’s Most Popular Processor Architecture
** Caminho Interno de Dados de 128 bits
** Getting Ready to Meet Intel Core 2 Duo: Página 5
* Intel(r) Integrated Performance Primitives (Intel(r) IPP)
** - Exemplos de Códigos em vários modelos de programações OpenMP, Pthreads, TBB. Multi-thread apps for Multi-core
** Intel Technology Magazine: Preparção de Aplicações para a Arquitetura Intel Core
* Benchmarks
** Intel Core 2 Extreme QX6700, uma avaliação do site bit-tech
** Defesa de Mestrado da Universidade da Lousiana Performance Analysis of Intel Core 2 Duo Processor
** Consumo máximo de vários processadores