Если у вас под рукой есть калькулятор, хоть виндовый, хоть в телефоне, можно за полминуты повторить опыт, который осенью 1994 года ставили у себя тысячи людей по всему миру: разделить 4195835 на 3145727, умножить результат обратно на 3145727 и вычесть исходное число. На исправном железе там выходит ноль, а на компьютере с ранним Pentium штатный калькулятор Windows спокойно показывал 256, и владелец новенькой машины, отдавший за нее пару-тройку тысяч долларов, впервые задумывался, можно ли верить процессору в такой простой вещи, как деление.

Ошибку нашел профессор математики из маленького колледжа в Вирджинии, который занимался простыми числами и относился к компьютерам примерно как плотник к рубанку, то есть вспоминал о них только тогда, когда стружка шла криво. Через полтора месяца после его письма про баг рассказывали в вечерних новостях CNN, IBM остановила поставки своих машин на Pentium, над Intel смеялись в ночных телешоу, а в январе 1995 года компания записала в убытки 475 миллионов долларов.

Обиднее всего для Intel в этой истории то, что исправить сам кремний ей почти ничего не стоило, потому что новую ревизию чипа она тихо запустила еще летом, задолго до того, как о проблеме узнал кто-то снаружи, и почти вся сумма набежала потом, за те несколько недель, пока компания объясняла покупателям, о чем им следует волноваться.

Близнецы из Линчберга

Томас Найсли преподавал в Линчбургском колледже и считал простые числа-близнецы, то есть пары вроде 11 и 13 или 29 и 31, которые отличаются ровно на два. Его интересовала константа Бруна, сумма обратных величин всех таких пар, которая сходится к числу около 1.902, и посчитать ее хоть с какой-то точностью получается только перебором, когда машины неделями складывают триллионы очень маленьких дробей и любая погрешность в далеком знаке рано или поздно всплывает при сверке. Трудно придумать задачу, которая лучше подходит для ловли ошибок в арифметике процессора, хотя ловить их Найсли совсем не собирался.

Расчеты шли параллельно на нескольких машинах, летом 1994 года к ним добавился компьютер с Pentium, и уже 13 июня Найсли заметил, что результаты на нем расходятся с тем, что выдают старые 486-е. Дальше началась работа, которую узнает любой, кто хоть раз гонялся за плавающим багом: четыре месяца он по очереди исключал собственный код, компилятор, чипсет материнской платы и прочих подозреваемых, пока к 19 октября в списке не остался один процессор. Сломанным оказалось обратное значение простого числа 824633702441, ошибка сидела где-то в девятом-десятом знаке, и обычный человек ее бы в жизни не заметил, а для суммы из миллиардов таких слагаемых она означала, что месяцы вычислений можно выбрасывать.

24 октября Найсли сообщил о проблеме в Intel, где ему фактически дали от ворот поворот, и тогда 30 октября он разослал письмо знакомым, у которых стояли Pentium, 486DX4 или клоны от других производителей, с просьбой прогнать у себя тест и рассказать, что получится, и с этого письма история перестала быть личным делом одного математика.

Пять пустых клеток

Чтобы понять, откуда взялась ошибка, надо вспомнить, зачем Intel вообще полезла в деление, ведь в 486-м оно работало по школьной схеме со сдвигом и вычитанием и выдавало один бит частного за такт, а Pentium хотелось сделать быстрее, поэтому в FPU поставили алгоритм SRT (по фамилиям Sweeney, Robertson и Tocher), который за такт выдает сразу два бита. Хитрость SRT в том, что очередную цифру частного он угадывает по таблице, глядя на старшие биты делителя и текущего остатка, цифра может быть одной из пяти, от -2 до +2, а небольшую неточность угадывания алгоритм потом сам выправляет на следующих шагах.

Таблицу в Pentium сделали в виде программируемой логической матрицы (PLA) на 2048 ячеек, из которых заполненными должны были быть 1066. Когда данные переносили в маску для производства, пять ячеек со значением +2 до литографии не доехали и в готовом кремнии в них оказались нули, а сама Intel объясняла это ошибкой в скрипте, который готовил таблицу. Кен Ширрифф, который в 2024 году разглядывал этот участок кристалла под микроскопом, насчитал шестнадцать пропавших ячеек, однако одиннадцать из них алгоритм никогда не читает, так что вредных осталось ровно пять, как Intel и говорила.

Когда деление попадает в такую ячейку, SRT берет ноль вместо двойки, и промах получается больше того, который он умеет исправить, поэтому он остается в результате и тянется через все следующие цифры. Попадают туда лишь те пары чисел, где у делителя в двоичной записи после первых битов идет длинная серия единиц, как у 3145727, который в шестнадцатеричном виде выглядит как 0x2FFFFF. Самую наглядную пару нашел Тим Коу из Vitesse Semiconductor, который по обрывкам описаний из сети собрал модель бага и искал, где ошибка выходит крупнее всего, и проверка на ней помещается в несколько строк:

double x = 4195835.0;
double y = 3145727.0;
double q = x / y;

printf("%.15f\n", q);        // 1.333820449136241 на исправном железе
printf("%.1f\n", x - q * y); // должен быть ноль, ранний Pentium выдавал 256

Для этой пары Pentium выдавал 1.333739068902037, то есть ошибался уже в четвертом знаке, и как раз такой пример, понятный любому бухгалтеру без всякой теории чисел, превратил математическую диковинку в новость для газет.

Тихая ревизия

К моменту письма Найсли Intel про баг уже знала, потому что собственные инженеры нашли его независимо примерно к июню 1994 года. Исправленную таблицу заложили в новые степпинги, D1 для Pentium на 60 и 66 МГц и B5 для моделей на 75, 90 и 100 МГц, а все, что уже лежало на складах и в магазинах, продолжали продавать без единого слова в документации.

Изнутри такое решение выглядит вполне по-инженерному, ведь у каждого процессора есть список известных ошибок, производители годами с этими списками живут, ошибка случается редко, отзыв стоит дорого, и тихо поменять маску, продолжая отгрузки, кажется разумной экономией. Беда в том, что в 1994 году Pentium покупали в том числе обычные люди, которым Intel несколько лет подряд по телевизору объясняла, что у них внутри стоит самое лучшее, и эти люди списков ошибок не читали, зато прекрасно умели делить в калькуляторе.

Письмо, которое ушло дальше адресатов

Письмо от 30 октября за считанные дни разошлось по CompuServe и Usenet, люди начали гонять тесты на своих машинах и выкладывать результаты, и все пошло по сценарию, для которого в 1994 году еще даже не придумали слова. 7 ноября вышла статья Александра Вулфа в Electronic Engineering Times, где Intel признавала ошибку и уверяла, что уже ее исправила, 22 ноября сюжет показал CNN, следом написали New York Times и Boston Globe, причем во втором случае на первой полосе.

Тут к истории подключились все, кто умел шутить, и Intel несколько недель подряд служила главной темой анекдотов, от ночных телешоу до подписей в почтовых рассылках. Самый живучий из них спрашивал, сколько инженеров Intel нужно, чтобы вкрутить лампочку, и отвечал, что 1.99904274017, но для нетехнических пользователей и так сойдет, причем в этой шутке довольно точно сформулирована позиция, которую компания тогда публично защищала.

Раз в 27000 лет

30 ноября Intel выпустила white paper со статистическим анализом, из которого следовало, что средний пользователь электронных таблиц наткнется на ошибку примерно раз в 27 000 лет, а журнал Byte позже прикинул, что на случайных операндах неверным выходит примерно одно деление из девяти миллиардов. Цифры выглядели солидно, но держались на допущении, что числа в реальных программах похожи на случайные, и с этим допущением 12 декабря поспорила IBM.

В своем отчете IBM показала, что в финансовых расчетах обычные десятичные значения после пары операций часто превращаются в двоичные числа с длинными сериями единиц, которые как раз и попадают в опасную зону таблицы, и по ее оценке пользователь таблиц мог получить ошибку где-то раз в 24 дня. Вместе с отчетом IBM объявила, что приостанавливает отгрузку компьютеров на Pentium, акции Intel за несколько часов просели примерно на десять пунктов, а в индустрии сразу вспомнили, что IBM в это время продвигала собственный PowerPC и от проблем конкурента ничего не теряла.

Кто был ближе к правде, спорят до сих пор, и большинство независимых оценок сходилось на том, что обычный пользователь бага скорее всего не увидит никогда. Тем, кто писал игры, повезло меньше: Джон Ромеро в 2019 году рассказывал, как Майкл Абраш во время работы над Quake раз за разом воспроизводил этот баг и часами выяснял точные условия, при которых куски уровня вдруг проступали на экране под определенными углами камеры, так что 27 000 лет у id Software, видимо, уложились в пару рабочих недель.

Справка о необходимости точности

Пока шли эти споры, Intel предлагала заменить процессор только тем, кто сможет доказать, что ошибка влияет на их работу, и получалось, что человек, купивший компьютер, должен был сначала объяснить производителю, зачем ему правильное деление. Энди Гроув, тогдашний глава компании, даже написал в конференцию comp.sys.intel, где признавал проблему и снова объяснял, насколько она редкая, и конференция отреагировала на это ровно так, как реагирует любой форум, когда директор приходит к нему лично.

Программисты тем временем чинили деление сами, кто как умел, и один из обходов работал так: проверял делитель и, если тот попадал в опасную зону, умножал и делимое, и делитель на 15/16, после чего деление уходило в безопасную часть таблицы, а на случайных данных такая проверка срабатывала примерно на пяти делителях из 1024 и стоила программе процент-другой скорости. В Wolfram Research пошли дальше и прямо в машинном коде уже выпущенных программ заменили инструкцию FDIV на недопустимую, чтобы процессор проваливался в обработчик исключения, а обработчик считал как надо, и подобный хак в проде, по-моему, заслуживает отдельной витрины в музее. Microsoft же добавила в Windows утилиту, которая находила баг и попросту отключала FPU, превращая дорогой процессор в очень быстрый компьютер без сопроцессора.

20 декабря, через неделю после заявления IBM, Intel сдалась и объявила, что поменяет процессор любому владельцу, который попросит, хотя реселлеров и сборщиков к программе замены так и не подпустили и менять чип каждому приходилось самостоятельно. Позже Гроув в интервью Wall Street Journal признал, что компания взялась решать за людей, о чем им стоит беспокоиться, и, пожалуй, более короткого описания всей истории так никто и не придумал.

Счет за молчание

17 января 1995 года Intel объявила о списании 475 миллионов долларов до налогов, куда вошли замена процессоров и списание запасов бракованных чипов, а в долларах 2026 года сумма тянет почти на 900 миллионов. Исправленную таблицу компания к тому моменту уже полгода выпускала в новых ревизиях, и стоимость самой починки на фоне этой цифры теряется где-то в погрешности, той самой, с которой все началось.

Забавно, что Pentium в эти месяцы продавался вполне бодро, и в годовом отчете за 1994 год Intel с некоторой гордостью писала, что продажи продолжали расти прямо во время скандала. Зато впервые в истории компьютерный чип отозвали целиком, и после этого никто в индустрии уже не мог делать вид, будто ошибки в кремнии остаются внутренним делом производителя.

Следующие годы Intel потратила на то, чтобы такое не повторилось, и в этом деле ей помогала вся индустрия: уже в 1996 году появился метод word-level model checking, придуманный в том числе ради проверки SRT-деления, при разработке Pentium 4 доказательство теорем поймало несколько ошибок, которые могли закончиться таким же отзывом, а в Nehalem 2008 года формальная верификация стала у Intel основным способом валидации. Плюс начиная с Pentium Pro процессоры научились принимать обновления микрокода, и часть ошибок, которые раньше означали замену железа, с тех пор закрывают патчем, приезжающим вместе с обновлением BIOS, о котором вы скорее всего даже не узнаете.

Часть бракованных Pentium Intel, кстати, залила в прозрачный пластик и сделала брелоки с фразой Гроува о том, что плохие компании кризис уничтожает, хорошие его переживают, а великие становятся после него лучше. Найсли же после всей этой истории продолжил считать свою константу и публиковал новые оценки еще много лет, и из всех участников этой истории он, похоже, единственный с самого начала хотел от процессора ровно одного, чтобы тот правильно делил.

Комментарии (5)