Entendendo a arquitetura NetBurst

A nova arquitetura do Pentium 4 foi batizada de NetBurst, um nome mercadológico usado para tentar ilustrar a arquitetura do processador e suas otimizações com relação ao processamento de grandes volumes de dados. Sempre que ouvir falar em um processador “baseado na arquitetura NetBurst”, tenha em mente que se trata de alguma derivação do Pentium 4, como um Pentium D ou Celeron D.

A principal característica da arquitetura NetBurst era o uso de um longo pipeline de processamento, batizado pela Intel de “Hyper Pipelined Technology”. Como vimos anteriormente, o primeiro processador Intel a utilizar um pipeline foi o 486, que possuía 5 estágios.

Como o 486 era um processador muito simples (para os padrões atuais), que processava uma instrução de cada vez, ele não precisava de muitos dos componentes usados nos processadores modernos, tais como o ordenador, circuito de branch-prediction e assim por diante. O processador simplesmente recebia cada instrução, fazia a decodificação e em seguida a executava. Enquanto a primeira instrução passava do primeiro para o segundo estágio do pipeline, o primeiro estágio recebia a instrução seguinte e assim por diante.

O Pentium 1 manteve os 5 estágios do 486, mas incorporou uma segunda unidade de execução e um coprocessador aritmético muito aprimorado. Com o uso de duas unidades de execução, surgiu a necessidade de dividir as instruções entre elas, o que gerou um problema adicional, já que a grande maioria dos programas executam processamento de maneira sequencial, esperando que o processador execute uma instrução de cada vez.

Surgiu então a necessidade de incluir circuitos adicionais, que ordenam as instruções de forma que o processador possa executar duas instruções por ciclo na maior parte do tempo. O mais importante deles é o circuito de branch prediction, que permite que o processador use o tempo ocioso para ir “adiantando o trabalho”, processando um dos caminhos possíveis em uma operação de tomada de decisão enquanto não sabe o resultado da operação que diz qual dos caminhos é o correto, como ao executar um trecho de código como este:

if [ a = b ]; then
bloco de código 1
else
bloco de código 2
fi

Aqui o processador só vai saber se deve executar o bloco de código 1, ou o bloco de código 2 depois que souber o resultado da primeira operação, ou seja, souber se “a” é igual a “b”. O circuito de branch prediction escolhe então o caminho que parece mais provável, permitindo que o processador permaneça ocupado. Quando o processador escolhe o caminho certo, ele ganha tempo, já que pode aproveitar o trabalho já feito. Mas, quando erra, ele precisa descartar todo o trabalho e recomeçar a partir do outro caminho.

O Pentium III era baseado em um pipeline de 10 estágios. Ao contrário do Pentium, que era um processador CISC, que processa todas as instruções x86 diretamente, o Pentium III e todos os demais processadores atuais, são processadores post-RISC, que quebram as instruções x86 em instruções simples, que são então processadas.

Graças à inclusão de todos os demais circuitos, uso do cache integrado e melhorias nas placas-mãe, o aumento no número de estágios de pipeline do Pentium III não teve um impacto muito negativo sobre o desempenho. Pelo contrário, um Pentium III era pelo menos duas vezes mais rápido que um Pentium 1 do mesmo clock.

Foi graças ao aumento no número de estágios no pipeline que o Pentium III foi capaz de atingir frequências de operação tão mais altas que o Pentium 1, que (com o MMX) atingiu apenas 233 MHz. Mesmo que fosse produzido em uma técnica de 0.18 micron, o Pentium provavelmente não seria capaz de superar a barreira dos 500 MHz, enquanto o Pentium III (de 0.18 micron) existiu em versões de até 1.0 GHz.

O Pentium 4 levou essa filosofia adiante, utilizando um total de 20 estágios de pipeline, daí o nome “Hyper Pipelined”. Temos aqui um slide da Intel que mostra um comparativo entre o pipeline do Pentium III com os 20 estágios do Willamette:

md619dab

Com mais estágios, cada um responde por uma fração menor do processamento, o que permite que o processador seja capaz de operar a frequências mais elevadas. Voltando ao exemplo da linha de produção, seria como se dobrássemos o número de operários e cada um passasse a encaixar apenas uma peça em cada produto que passa através da esteira, em vez de duas. Reduzindo o trabalho de cada operário pela metade, seria possível mover a esteira ao dobro da velocidade, dobrando a produção.

O grande problema é que os processadores atuais executam várias instruções simultaneamente (enquanto os aplicativos são compostos por sequencias de instruções), de forma que sempre existe uma penalidade em adicionar mais estágios. Quanto mais estágios, mais tempo o processador demora para executar as instruções iniciais de tomada de decisão e mais tempo perde ao escolher o caminho errado.

Ainda no exemplo da linha de produção seria como se o produto a ser montado mudasse constantemente, de acordo com os pedidos recebidos dos clientes. Cada vez que o produto muda, é preciso parar a esteira, desmontar as unidades do produto anterior que já estavam parcialmente montadas e limpar a esteira, para só então poder recomeçar a produção.

No Pentium 4, a cada tomada de decisão errada são perdidos pelo menos 20 ciclos de processamento, uma eternidade considerando que em média, 14% das instruções processadas são de tomada de decisão. A partir de um certo ponto, aumentar o número de estágios torna-se contra produtivo, já que o processador precisa operar a frequências de clock cada vez mais altas para compensar a perda de desempenho causada pelo maior número de estágios. Um bom exemplo disto é o Pentium 4 com core Prescott (que veremos a seguir), que precisou incorporar um conjunto de várias melhorias apenas para compensar a perda de desempenho causada pelo novo aumento no número de estágios.

Além da perda de desempenho, outro efeito colateral de se usar mais estágios de pipeline é o fato de tornar o processador maior e mais complexo e fatalmente bem mais caro de se produzir. O Pentium 4 de 0.18 micron media 217 milímetros quadrados, quase o dobro do Athlon Thunderbird, que media 120 mm². Isso significa que o Pentium 4 era proporcionalmente mais caro de se produzir.

Continuando, tínhamos a questão do cache. O Pentium III utilizava 32 KB de cache L1 (16 KB para dados e mais 16 KB para instruções), enquanto o Athlon inovou com um L1 de surpreendentes 128 KB.

No Pentium 4, o bloco do cache L1 destinado a instruções foi substituído pelo execution trace cache, um tipo de cache ultra-rápido que armazenava diretamente uOPs, que são as instruções já decodificadas, prontas para serem processadas. Isso permitia que o cache operasse com apenas um ciclo de latência (a instrução é solicitada em um ciclo e recebida no seguinte), diferente de outros processadores, onde as instruções lidas no cache precisam ser primeiro decodificadas.

O trace cache ocupava uma área muito grande do die do processador, equivalente ao que seria ocupado por aproximadamente 96 KB de cache L1 convencional. Apesar disso, ele armazenava o equivalente a apenas 8 KB de instruções decodificadas, já que elas ocupavam brutalmente mais espaço. Ou seja, por um lado o trace cache melhora o desempenho do processador, já que é muito rápido, mas por outro diminui (em relação ao que seria obtido ao utilizar um cache convencional de maior capacidade), pois o pequeno volume de dados armazenados fazia com que ele precisasse recorrer mais frequentemente aos dados armazenados no cache L2 e na memória principal. Isso fez com que o trace cache fosse abandonado a partir do Core 2 Duo.

O trace cache era complementado por um cache de dados de baixa latência, consideravelmente mais rápido que o cache L1 encontrado no Pentium III e no Athlon. O problema é que, para atingir o desempenho desejado, o circuito do cache se tornou extremamente volumoso, o que levou a Intel a reduzir a capacidade, incluindo apenas 8 KB. Ou seja, na prática, o Pentium 4 possuía apenas 16 KB de cache L1: 8 KB para dados e mais o equivalente a 8 KB para instruções, armazenadas de forma decodificada no trace cache.

Para complicar, o Willamette utilizava apenas 256 KB de cache L2, o que resultava em um sistema de cache bastante rápido, mas capaz de armazenar apenas um pequeno volume de dados. Isso fez com que o processador se tornasse muito mais dependente da velocidade de acesso à memória.

O plano inicial da Intel era utilizar módulos de memória Rambus em dual-channel. Cada módulo RIMM oferecia (no caso dos módulos PC-800) um barramento de dados de 1.6 GB/s, de forma que combinando a banda oferecida por dois módulos, seria possível obter 3.2 GB/s, o que é 3 vezes o oferecido pelos módulos de memória PC-133 utilizados pelo Pentium III.

Para absorver esse grande volume de dados, o Pentium 4 adotou o uso de um barramento quad-pumped, ou seja, capaz de realizar 4 transferências por ciclo. Operando a 100 MHz, temos uma taxa efetiva de 400 MHz, que é a frequência utilizada nas primeiras placas soquete 423.

Com a evolução da plataforma, a Intel foi capaz de desenvolver chipsets capazes a operar a 133, 200 e 266 MHz, que, com as 4 transferências por ciclo, equivalem a, respectivamente, 533, 800 e 1066 MHz. Embora o Willamette tenha ficado restrito aos 400 MHz originais, as frequências mais altas foram utilizadas pelos processadores lançados posteriormente. Ao contrário do processador, o barramento de dados se revelou bastante eficiente, continuando a ser usado no Core 2 Duo.

Continuando, embora o Pentium 4 fosse consideravelmente mais lento quando usado em conjunto com memórias SDRAM, as memórias DDR reduziram a perda de forma expressiva. A partir de um certo ponto cada vez mais placas passaram a suportar o uso de memórias DDR em dual-channel, configuração que superava as memórias Rambus em desempenho (já que além da maior taxa de transferência, oferecia tempos de latência mais baixos).

Na parte de processamento de instruções o Pentium 4 ganhou um reforço nas unidades de processamento de inteiros, tecnologia batizada pela Intel de “Rapid Execution Engine”.

Todo processador atual é dividido em dois componentes básicos, as unidades de execução de inteiros e as unidades de ponto flutuante (FPU). A parte que processa as instruções envolvendo números inteiros é responsável pela maior parte das instruções e pelo desempenho do processador nos aplicativos do dia-a-dia, enquanto as unidades de ponto flutuante são as responsáveis pelo processamento das instruções envolvendo valores complexos, usadas por jogos, aplicativos gráficos e conversores de mídia.

O Pentium 4 possui um total de 3 unidades de processamento de inteiros, duas ALUs, que processam as instruções mais simples e uma terceira ALU, encarregada de decodificar e processar as instruções complexas que, embora em menor quantidade, são as que tomam mais tempo do processador.

Esse conjunto de 3 unidades de execução de inteiros é semelhante ao do Pentium III, porém, como diferencial, no Pentium 4 tanto as duas ALUs encarregadas das instruções simples quanto as duas GLUs encarregadas das leituras e gravações executam duas instruções por ciclo, de forma que, em um Willamette de 2.0 GHz, elas atingem uma frequência efetiva de nada menos que 4.0 GHz.

Entretanto, existe um pequeno detalhe que elimina boa parte do ganho que seria de se esperar deste esquema. Apesar das duas ALUs de instruções simples terem ficado mais rápidas, visando justamente compensar a perda de desempenho trazida pelos 20 estágios de pipeline do Pentium 4, a ALU de instruções complexas não teve a mesma evolução. Isto significa que ao passar a usar 20 estágios de pipeline, a terceira ALU tornou-se mais lenta que a do Pentium III.

Tínhamos então um cenário onde as instruções simples são rapidamente processadas, mas as instruções complexas ficavam entaladas na vala comum da terceira ALU, causando uma grande perda de desempenho.

No coprocessador aritmético o cenário era ainda mais complicado, pois apesar das unidades de execução terem perdido desempenho devido ao pipeline de 20 estágios, não houve nenhum avanço capaz para equilibrar a balança, como tivemos nas unidades de inteiros.

Ao invés de evoluir, como seria de se esperar, o coprocessador aritmético do Pentium 4 tornou-se ainda mais frágil do que o do Pentium III, trazendo um cenário curioso. Enquanto na época do Pentium II e do K6 a AMD competia com um processador que, apesar de possuir um bom desempenho em aplicativos de escritório, era massacrado nos jogos e aplicativos gráficos, tivemos com o Pentium 4 x Athlon um cenário semelhante, porém com os lados invertidos: a Intel atacava com um processador potente em inteiros, mas fraco em ponto flutuante.

Ironicamente, a solução da Intel para tentar diminuir a deficiência do processador em ponto flutuante foi a mesma que a AMD usou na época do K6-2: oferecer um novo conjunto de instruções capaz de aproveitar melhor os recursos do processador.

O Pentium 4 trouxe também o suporte ao conjunto SSE2, composto de 144 novas instruções de ponto flutuante de dupla precisão. O SSE2 trouxe vários avanços sobre a primeira versão e recebeu uma boa dose de apoio por parte dos desenvolvedores, o que ajudou o Pentium 4 em muitos aplicativos. Mais tarde, a AMD respondeu adicionando um conjunto compatível no Athlon 64, equilibrando a briga.

Vale lembrar que tanto o Pentium 4 quanto os processadores AMD (a partir do Athlon Palomino) são compatíveis também com as instruções SSE do Pentium III, o que faz com que eles se beneficiem também dos aplicativos otimizados para o conjunto anterior.

Sobre o Autor

Redes Sociais:

Deixe seu comentário

X