O erro de US$ 475 milhões da Intel: o problema de silício por trás do bug de divisão do Pentium
(righto.com)- O Pentium, lançado em 1993, adotou o método SRT para fazer divisão de ponto flutuante mais rápido que o Intel 486, mas em 1994 o erro da instrução FDIV veio a público, e a Intel concordou em substituir todos os chips defeituosos, a um custo de US$ 475 milhões
- O defeito estava na tabela de consulta implementada no PLA para divisões; a Intel disse que 5 entradas haviam sido omitidas por um erro de script, mas a análise do die aponta 16 omissões, das quais 5 realmente causavam erro
- A divisão SRT radix-4 é rápida porque produz 2 bits do quociente por etapa, mas usa uma estrutura complexa que mapeia resto parcial e divisor em uma tabela P-D de 2048 entradas, depois comprimida em um PLA de 112 linhas
- A causa central é que, por causa do carry-save adder, o índice de consulta pode cair uma célula abaixo do resto parcial real; a Intel aplicou uma correção matemática incorreta no limite superior da região +2, deixando algumas células em 0
- O Pentium corrigido não apenas preencheu as 5 entradas ausentes, mas definiu toda a área não usada da tabela como 2, simplificando os limites; as linhas usadas no PLA também caíram de 120 para 74, deixando-o cerca de 1/3 menor que o PLA defeituoso
Como o bug FDIV veio a público e quanto custou
- A Intel lançou o processador Pentium de alto desempenho em 1993 e incluiu um algoritmo de divisão de ponto flutuante mais rápido que o do Intel 486 anterior
- Em maio de 1994, testes internos da Intel descobriram que a divisão de ponto flutuante do Pentium às vezes produzia resultados incorretos, embora muito raramente
- A Intel estimou que o problema ocorria em apenas 1 valor entre 9 bilhões e o tratou como algo menor
- Ainda assim, o circuito do Pentium foi corrigido silenciosamente
- Em outubro de 1994, o professor Thomas Nicely encontrou resultados errados ao pesquisar recíprocos de primos gêmeos
- O cálculo de
1/824633702441estava errado em três computadores Pentium diferentes, enquanto máquinas anteriores davam a resposta correta - Sem obter resposta adequada do suporte técnico da Intel, Nicely enviou e-mails para revistas de informática e contatos pessoais
- Esse e-mail foi parar em um fórum da Compuserve, e a Electronic Engineering Times publicou em 7 de novembro Intel fixes a Pentium FPU glitch
- O cálculo de
- No início, a Intel queria oferecer troca apenas a clientes que convencessem um engenheiro de que precisavam de precisão, e usuários reclamaram em grupos online como comp.sys.intel
- Depois de uma reportagem da CNN em 22 de novembro, o interesse público aumentou, e a situação piorou em 12 de dezembro, quando a IBM anunciou a suspensão do envio de computadores com Pentium
- Em 19 de dezembro, a Intel anunciou que substituiria os chips defeituosos para todos os clientes
- O custo do recall foi de US$ 475 milhões
- Em valores atuais, isso passa de US$ 1 bilhão
A divisão SRT usada pelo Pentium
- A divisão binária longa tradicional é lenta porque exige um ciclo de clock para cada bit do quociente
- O Intel 486 e processadores anteriores usavam essa abordagem
- O Pentium usava o algoritmo SRT em radix-4, ou seja, em unidades de 2 bits
- Cada etapa gera 2 bits do quociente, ficando duas vezes mais rápido que a divisão binária comum
- Cada dígito do quociente pode ser
-2,-1,0,1ou2
- Como o SRT permite dígitos negativos no quociente, mesmo que uma etapa escolha um valor um pouco alto, a etapa seguinte pode compensar com um dígito negativo
- Como o dígito do quociente não precisa ser determinado de forma única, ele pode ser escolhido rapidamente por tabela de consulta
- Alguns bits do resto parcial e do divisor são recortados para manter o tamanho da tabela em nível prático
- Esse método é rápido, mas exige também uma tabela de consulta, circuitos para somar ou subtrair múltiplos de
1ou2, e circuitos para converter ao formato padrão de quociente
A estrutura que comprimia uma tabela de 2048 entradas em um PLA de 112 linhas
- A tabela de consulta SRT do Pentium recebe como entrada o resto parcial
pe o divisord, e produz o dígito de quociente apropriado - A tabela é formada por 2048 entradas
- O divisor é escalado entre 1 e 2 e forma a coordenada do eixo X
- O resto parcial fica entre -8 e 8 e forma a coordenada do eixo Y
- Do divisor
1.dddd, usam-se 4 bits excluindo o primeiro bit, que é sempre 1 - O resto parcial é truncado para um valor signed de 7 bits,
pppp.ppp - O índice total tem 11 bits, apontando para
2^11 = 2048entradas
- A tabela tem 5 regiões correspondentes aos dígitos de quociente
+2,+1,0,-1e-2- Algumas regiões superior e inferior não são usadas pela matemática do SRT
- Na tabela defeituosa original, as entradas não usadas eram preenchidas com 0
- As 5 entradas problemáticas em vermelho deveriam ser
+2, mas permaneceram em 0
- O Pentium implementava essa tabela não como ROM, mas como PLA (Programmable Logic Array)
- Guardar toda a tabela como ROM exigiria 2048 linhas
- Como a estrutura da tabela é regular e tem muitas áreas vazias, o PLA precisava de apenas 112 linhas
- O PLA é composto por um plano AND e um plano OR
- O plano AND gera termos lógicos a partir de combinações de bits de entrada e seus complementos
- O plano OR combina esses termos para criar bits de saída que indicam se o quociente é
1ou2
- Extraindo ao microscópio o padrão de transistores do PLA, é possível reconstruir as expressões lógicas de cada linha do PLA
- Uma linha do PLA não corresponde a uma única célula da tabela, mas atua como uma região retangular que cobre várias células de uma vez
- Quanto mais irregular for um limite específico da tabela, mais linhas de PLA serão necessárias
Limites matemáticos e a região +2 incorreta
- A etapa central da divisão SRT é escolher o dígito de quociente
qpela razãop/dentre o resto parcialpe o divisord - Por motivos matemáticos, a faixa permitida de
p/ddeve ficar em[-8/3, 8/3]- Depois de escolher o dígito do quociente, subtrai-se
q*de multiplica-se por 4 para gerar o resto parcial da próxima etapa - Para que esse processo possa se repetir, a nova faixa precisa ter o mesmo tamanho da original
- Depois de escolher o dígito do quociente, subtrai-se
- O SRT tem redundância, então em alguns intervalos pode-se escolher qualquer um entre dois dígitos de quociente
- Mas se for escolhido
0ondeq=2era obrigatório, o próximo resto parcial sai da faixa permitida e o algoritmo não consegue se recuperar - O bug FDIV era exatamente esse caso
- Mas se for escolhido
- A tabela P-D do Pentium é uma quantização desses limites matemáticos em células discretas
- Os limites diagonais determinam se uma célula deve ser obrigatoriamente
+2, pode ser+1ou+2, deve ser obrigatoriamente+1etc.
- Os limites diagonais determinam se uma célula deve ser obrigatoriamente
- A análise do die mostrou que a linha de limite magenta superior da tabela defeituosa deveria ficar sempre acima da linha de limite matemática preta, mas a cruza repetidamente
- Como resultado, algumas células que tinham de ser
+2ficaram em 0 - Essas células eram as entradas omitidas que causavam o bug FDIV
- Como resultado, algumas células que tinham de ser
Como o carry-save adder tornava o erro raro, mas decisivo
- O circuito de divisão do Pentium usava um carry-save adder para acelerar somas e subtrações
- Um carry-save adder não propaga imediatamente o carry, guardando-o em uma palavra separada, o que ajuda em divisões que exigem várias somas
- No final, ainda é necessária uma soma mais lenta para combinar os carries armazenados
- O índice da tabela de consulta precisa do resto parcial, mas o carry-save adder mantém esse resto parcial dividido em bits de soma e bits de carry
- Para calcular rapidamente apenas os 7 bits necessários ao índice da tabela, o Pentium usava um carry-lookahead adder
- Esse circuito calcula os carries de cada posição em paralelo
- Em palavras grandes ele fica complexo demais, mas para um valor de 7 bits é prático
- O problema é que o resto parcial tem 64 bits, enquanto o cálculo do índice da tabela usa apenas 7 bits
- Os bits restantes são descartados antes da soma final, e assim o resto parcial usado no índice pode ficar um pouco abaixo do valor real
- Especificamente, isso pode gerar uma célula uma posição abaixo da correta, isto é, um deslocamento de
1/8
- Por causa desse efeito, alguns limites precisavam ser deslocados
1/8para baixo, mas nem todos deveriam ser movidos- O limite superior da região
+2não deveria ser deslocado para baixo, mas a Intel gerou uma tabela em que ele foi deslocado incorretamente - Esse efeito do carry-save já era conhecido e inclusive aparecia em artigos sobre divisão SRT da época
- O limite superior da região
Onde a explicação da Intel diverge da análise do die
- Um white paper da Intel afirmou que houve um problema no script que colocava a tabela dentro do PLA, fazendo com que algumas entradas fossem omitidas
- A Intel chamou isso de Programmable Lookup Array, mas a estrutura real era um Programmable Logic Array
- A análise do die sugere que as entradas ausentes combinam melhor com um erro de limite matemático do que com um simples erro de cópia
- É possível que o programa que gerava a tabela tivesse definido incorretamente as condições de contorno
- A palavra “script” pode até ser tecnicamente correta se significar um programa em C que gerava a tabela, mas a interpretação é que a essência do problema foi um limite matemático errado
- The Pentium Chronicles, de Robert Colwell, oferece outra explicação
- Segundo ela, o projeto do Pentium originalmente usava a mesma tabela de consulta do 486 e, perto do lançamento, ao otimizar para economizar área de die, surgiu o erro
- Essa explicação tem pontos que não batem
- O Pentium usava desde o início um algoritmo de divisão diferente do 486
- O Pentium usava SRT radix-4, enquanto o 486 usava divisão binária padrão
- O 486 não tinha essa tabela de consulta
- O PLA defeituoso ainda tinha 8 linhas não usadas, então, se a meta fosse apenas reduzir o circuito, essas linhas poderiam ter sido removidas primeiro
Por que o PLA corrigido ficou menor
- Na época, reportagens diziam que a Intel havia corrigido o defeito adicionando algumas dezenas de transistores ou uma sequência extra de portas ao PLA
- O PLA corrigido visto no die mostra exatamente o oposto
- O tamanho do PLA permaneceu o mesmo
- Cerca de 1/3 dos termos foi removido
- Apenas 74 das 120 linhas eram usadas, e as outras 46 ficaram vazias
- O PLA defeituoso original tinha 8 linhas vazias
- A correção da Intel não consistiu apenas em preencher as 5 entradas ausentes com
2- Toda a área não usada da tabela passou a ser preenchida com 2
- Isso eliminou a possibilidade de acessar por engano uma entrada vazia
- Ao preencher a área não usada com 2, os limites da tabela ficaram mais simples
- Limites irregulares exigem muitos termos de PLA
- Regiões retangulares grandes podem ser cobertas por um único termo de PLA
- Assim, mesmo com mais células da tabela preenchidas, as expressões do PLA ficaram mais simples
- Como os termos lógicos do PLA corrigido são completamente diferentes dos do PLA original, é difícil apontar alguns transistores específicos e dizer que foram eles que corrigiram o bug
Impacto real e controvérsia
- Em divisões aleatórias, a probabilidade de o defeito ocorrer era extremamente baixa, cerca de 1 em 9 bilhões
- Mesmo quando a divisão saía errada, a diferença normalmente aparecia só na 9ª ou 10ª casa decimal
- Em casos raros de pior cenário, o erro podia aparecer já no 4º dígito significativo
- Em seu white paper, a Intel estimou que um usuário comum encontraria o problema apenas uma vez a cada 27 mil anos
- Disse também que, para a maioria dos usuários, isso não seria um problema, embora alguns usuários de áreas científicas, de engenharia e de engenharia financeira pudessem precisar de um processador corrigido ou de contorno via software
- Em sua própria análise, a IBM concluiu que clientes poderiam enfrentar o problema a cada poucos dias e interrompeu a venda de Pentiums
- A IBM também tinha, na época, o processador concorrente PowerPC
- Há avaliações de que, no uso real, a única pessoa que de fato detectou o bug foi o professor Nicely
- A análise da IBM é vista como tendo escolhido números especialmente propensos a disparar o erro
- A maioria dos usuários provavelmente nunca encontraria o bug e, mesmo encontrando, uma pequena perda de precisão em ponto flutuante talvez não causasse problema
- Mas o bug FDIV era determinístico
- Se um determinado dividendo e divisor acionassem o problema, o resultado sairia errado em 100% das vezes
- Como os clientes podiam reproduzi-lo facilmente em suas próprias máquinas, era difícil para a Intel sustentar a ideia de que era um problema “que ninguém jamais encontraria”
Bugs posteriores em processadores e microcódigo atualizável
- O bug FDIV é um dos bugs de processador mais famosos, mas a Intel teve outros defeitos importantes
- Alguns processadores 386 iniciais tinham um problema com multiplicação de 32 bits
- Em certas combinações de temperatura, tensão e frequência, produziam resultados incorretos de forma imprevisível
- A causa era um problema de layout com margem elétrica insuficiente
- A Intel vendeu esses chips defeituosos apenas para o mercado de 16 bits, marcando-os como “16 BIT S/W ONLY”
- Outro problema do Pentium foi o bug F00F, descoberto em 1997
- Uma sequência específica de instruções começando com
F0 0Ftravava o processador até a reinicialização - O problema foi resolvido por atualização do sistema operacional
- Uma sequência específica de instruções começando com
- O Pentium tinha o microcódigo gravado em ROM, então o bug FDIV não podia ser corrigido com atualização de microcódigo
- Em 1995, a Intel adicionou microcódigo atualizável ao Pentium Pro
- Originalmente, isso servia para depuração e testes do chip
- Depois do bug FDIV, ficou claro que isso também tinha valor para correção de bugs
- O Pentium Pro tinha microcódigo em ROM e também SRAM capaz de armazenar até 60 microinstruções, permitindo ao BIOS carregar patches durante a inicialização
- Hoje, patches de microcódigo em processadores Intel modernos são usados para vários tipos de problemas, de vulnerabilidades como Spectre a problemas de tensão
O erro causado por circuitos cada vez mais complexos
- Com a lei de Moore, o número de transistores nos processadores aumentou, e os circuitos e algoritmos também ficaram mais complexos
- A evolução do suporte a divisão mostra isso com clareza
- O Intel 8080 usava 6000 transistores em 1974 e não oferecia divisão em hardware nem aritmética de ponto flutuante
- O Intel 8086 usava 29 mil transistores em 1978 e implementava divisão inteira em microcódigo, mas exigia o coprocesador 8087 para ponto flutuante
- O Intel 486, em 1989, com 1,2 milhão de transistores, integrou o suporte a ponto flutuante no chip
- O Pentium, em 1993, com 3,1 milhões de transistores, adotou o algoritmo de divisão SRT, mais rápido porém mais complexo
- Só o PLA de divisão do Pentium tinha cerca de 4900 posições de transistores
- Isso já é mais do que o processador inteiro MOS Technology 6502
- Ou seja, um único componente do circuito de divisão do Pentium usava mais transistores do que um processador completo de 1975
- O impacto de longo prazo do bug FDIV é debatido
- Concorrentes como a AMD lucraram com anúncios zombando do problema do Pentium
- Robert Colwell considera que o bug FDIV pode até ter tido efeito líquido positivo, ao aumentar muito o reconhecimento da marca Pentium e mostrar que a Intel sustentava sua marca
- A Intel sobreviveu ao bug FDIV, mas o defeito da época mostrou que, quando matemática complexa, compressão de circuitos e limites de verificação se combinam, até erros extremamente raros podem virar um grande problema de confiança
1 comentários
Opiniões do Hacker News
Sou o autor. Se houver perguntas sobre o Pentium, posso responder :-)
Uma thread no Mastodon sobre esse bug apareceu no HN algumas semanas atrás, então talvez seja familiar, mas agora concluí um post detalhado no blog. O post anterior no HN também tem bastantes comentários: https://news.ycombinator.com/item?id=42391079
Houve erros piores dentro da própria Intel e também em outras empresas, mas esses foram completamente esquecidos. Tenho curiosidade sobre a pilha de valores da unidade de ponto flutuante do Pentium — não sei o nome exato — e sobre essa reformulação. Faz muito tempo, mas será que não fizeram algo como uma forma inicial de renomeação de registradores (register renaming), que precisava ser gerenciada manualmente com cuidado usando
fxchg?Quão difícil seria “despejar” o microcódigo como um bitstream? Seria possível fazer isso programaticamente a partir de fotos de alta resolução do die? Claro, isso talvez seja a parte fácil em comparação com a engenharia reversa do significado desse bitstream
Também fiquei curioso com a parte “examinamos cuidadosamente o PLA ao microscópio”. Esse tipo de trabalho é feito em casa? Que equipamentos há no laboratório? Como se aprende esse tipo de técnica?
Em retrospecto, fico me perguntando por que as partes não usadas da tabela de consulta não foram preenchidas desde o início com 2 e -2
O bug em si é interessante, mas a resposta da Intel também é fascinante por si só. Pelo que parece, eles não substituíram por processadores sem defeito para todos que quiseram, e isso gerou uma péssima repercussão
Como comparação, isso me lembra muito o lançamento do Amazon Colorsoft. Alguns aparelhos, incluindo o meu, tinham um problema gráfico de faixa amarela; a Amazon levou um ou dois dias para verificar os fatos, reconheceu o problema e depois passou a trocar tudo silenciosamente. Nem foi um recall: se você pede, eles enviam um produto novo. Minha unidade de substituição chega na sexta-feira, e espero que resolva. Quando um lançamento dá errado, fica claro que ter uma estrutura de devolução/suporte muito sólida é uma vantagem muito maior do que se costuma prever em análises
De forma parecida, o problema de ruído dos Apple AirPods Pro de alguns anos atrás também não recebeu tanta cobertura recentemente. Meus AirPods precisaram ser trocados duas vezes, mas a Apple também fez a troca discretamente, e a sensação foi de que a capacidade de suporte, embora pouco visível por fora, funcionava de maneira bastante poderosa
Colorsoft: https://www.tomsguide.com/tablets/e-readers/amazon-kindle-co...
AirPods Pro: https://support.apple.com/airpods-pro-service-program-sound-...
Do lado da Apple, o Antennagate do iPhone 4 seria uma comparação melhor. Ali, a solução equivalente teria sido substituir gratuitamente o principal produto carro-chefe em termos de receita, mas a Apple não fez isso
Já a Intel acabou oferecendo substituição gratuita a qualquer pessoa que solicitasse, assumindo um grande impacto financeiro
Esse jeito da Apple de se responsabilizar pelo produto era realmente digno de respeito
Já passei por situações de “garantia informal” da Apple para consumidores, então entendo o que você quer dizer, mas acho que era algo muito diferente da crise de TI que a Intel enfrentou. Na época, a frase “a IBM disse isso” tinha um peso enorme em TI
O white paper da Intel dizia que um usuário comum encontraria o problema uma vez a cada 27.000 anos, e que isso era desprezível em comparação com outras causas de erro, como bit flips em DRAM. Já a IBM, em sua própria análise, estimou que um cliente poderia se deparar com isso a cada poucos dias
Acho que os dois números talvez não estejam tão distantes quanto parecem. A Intel parece ter considerado um único usuário, enquanto a IBM possivelmente pensou do ponto de vista de chamados de suporte
Já passei por algo parecido no trabalho. Se você processa 100 milhões de requisições por dia, um problema de uma em um bilhão aparece algumas vezes por mês. Se for do tipo que um cliente — ou pior, um gerente — percebe, as pessoas ignoram o denominador e começam a suspeitar que todo mundo é incompetente. Quatro vezes por mês podem ser traduzidas como “sempre” dentro do viés da experiência humana. Se surgirem dois agrupamentos estatísticos de três vezes por semana, alguém vai explodir
Também considerou que os números usados pelas pessoas tinham 90 vezes mais chance de causar erro do que os números de distribuição uniforme da Intel. Daí saiu o resultado de que um usuário encontraria um erro a cada 24 dias
Há um trecho que diz: “parece que a única pessoa que percebeu esse bug em uso real foi o professor Nicely”
Isso me lembra um estudo antigo em que deram calculadoras a alunos para uma aula de matemática. As calculadoras tinham sido adulteradas para produzir resultados errados, e os pesquisadores queriam saber quão errada a calculadora precisava estar para que os alunos notassem algo estranho
A resposta foi 2 vezes
Perceber um erro e ser afetado por um erro são coisas completamente diferentes. Quantas pessoas verificam se a saída do computador está correta? Muito, muito, muito poucas, eu acho. Eu também não fazia isso, exceto por uma vez na Boeing, ao fazer cálculos de engenharia, em que rodei as equações ao contrário para verificar se a saída batia com a entrada
No fim, depende muito do contexto e de quanto a pessoa que está fazendo o cálculo entende do assunto
No Pentium, quanto do uso de FDIV era para saídas numericamente importantes, e não para multimídia?
Lembro desse bug. Como não havia como controlar em qual CPU o cliente executaria o código, tivemos que colocar na biblioteca um código de detecção de FPU defeituosa e executar um desvio. Esse código foi fornecido pela Intel
Ou seja, o problema da Intel virou problema meu, argh
Lembro de uma piada que circulava na época. Capturava bem vários climas dos anos 90:
I AM PENTIUM OF BORG.
DIVISION IS FUTILE.
YOU WILL BE APPROXIMATED.
Mais um ótimo texto do Ken. Lembro especialmente dele porque o primeiro PC que comprei com meu próprio dinheiro tinha uma CPU afetada. Antes disso, eu não me interessava muito por PCs porque eles não conseguiam rodar software “de verdade”
Mas o Windows NT mudou isso, e agradeço ao Cutler por isso. As placas-mãe baratas de Taiwan também tornaram viável montar a própria máquina, algo que muita gente ainda faz. Ken apontou que era fácil para os usuários verificarem se a própria CPU era afetada. Lembro que era algo tão simples quanto digitar no Excel uma fórmula de divisão com números mágicos. Se a Microsoft tivesse lançado uma versão do Excel que contornasse o bug, acho que menos usuários teriam pedido substituição
É uma análise interessante e realmente obstinada. O esforço de analisar o silício e compartilhar os resultados é impressionante. Gostei especialmente de como o PR da Intel fazia a causa real soar como uma pequena omissão, enquanto o texto identificou a verdadeira causa raiz
Na verdade, era um problema muito menos perdoável e muito mais condenável. Afinal, eles tinham estragado o algoritmo de geração da tabela
A frase “Smith postou esse e-mail no fórum Compuserve, a versão dos anos 1990 das redes sociais” me deixa com uma sensação estranha
A tabela corrigida ficou muito mais simples ao não adicionar um circuito que retornasse 0 para valores fora do intervalo, mas simplesmente retornasse 2. Então fico me perguntando por que não fizeram isso desde o início
A pessoa que gerou a tabela não sabia que preencher fora do intervalo com 2 resultaria em uma PLA mais simples, e a pessoa que enfiou a tabela na PLA talvez não soubesse que 0 era um valor irrelevante (don't care) e presumiu que precisava ser preservado
Ou talvez tenham parado de otimizar no momento em que sentiram que a PLA já estava pequena o suficiente. Se o planejamento de layout já estivesse concluído, deixar a PLA ainda menor não tornaria o chip inteiro menor, e o tempo de engenharia seria melhor gasto em outro lugar
Como na maior parte do software, havia uma otimização deixada para trás porque ninguém pensou nela a tempo. E CPUs dessa época não podiam ser corrigidas por patch