14 июня 2021 г.

Cores that don't count: "тихие" производственные дефекты процессоров

TL;DR: Инженеры гугла утверждают, что примерно 0.1% современных процессоров содержат дефекты, ускользнувшие от техконтроля производителя, из-за чего некоторые инструкции на таких процессорах втихую дают неправильный результат. Вероятно, доля таких производственных дефектов будет расти. Вероятно, пора отвыкать думать о процессоре как об идеальном вычислителе, и искать способы создавать такие программные системы, которые обнаруживают и компенсируют ошибки CPU.

В твиттере проскочил очень интересный доклад Питера Хошчилда (Peter H. Hochschild) из гугл на конференции HotOS 20211

Питер со своей командой обнаружили, что в современных процессорах существует заметное количество скрытых дефектов ("mercurial errors"), которые более-менее регулярно приводят к неверным результатам вычислений. Вероятно, это дефекты производства, которые просочились сквозь техконтроль производителя.

Это не систематическая производственная ошибка, как Pentium FDIV bug. Это не случайное переключение логического элемента пролетевшей заряженной частицей. Это дефект, приводящий к воспроизводимой2 ошибке в работе конкретного экземпляра процессора3. Что особенно неприятно: ошибка не приводит к остановке (fail-stop) процессора – нет, процессор продолжает работать, только результат некоторых инструкций оказывается неверным.

При этом процессор проходит стандартные тесты (что логично: иначе он не прошел бы техконтроль производителя), но за пределами стандартных тестов что-то работает не правильно.

И они даже не первые, кто это обнаружил – в феврале о подобном же сообщала команда из фейсбука4

Насколько это актуально за пределами google?

Насколько часто встречаются такие дефекты ("mercurial core")? NDA не позволяет авторам озвучивать точные цифры, но речь идет о нескольких случаях на тысячи серверов – это примерно (0.01 .. 0.1)% вероятности встретить дефектное ядро в сервере.

И это много: получается, что в скромном парке из 50 серверов уже (1:200 .. 1:20) шанс встретить дефектное ядро. У нас на одном этаже сидят несколько десятков команд, и у каждой от десятков до сотен серверов в распоряжении – получается, почти наверняка кто-то из них сталкивается с дефектными процессорами.

Но надо иметь в виду, что дефекты проявляются не каждый раз, и обычно в каких-то необычных вычислениях и режимах работы (опять же: иначе их поймал бы техконтроль производителя). Т.е. даже если вам и попалось дефектное ядро – его дефектность может и не проявлять себя на тех вычислениях, и в тех режимах работы, в которых вы его используете.

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

Выглядит так, что, проблема действительно маячит на горизонте – не только для гугла с фейсбуком, но и тех, кто поменьше – но все еще сложно оценить, насколько близко она маячит именно к нам.

Это что-то принципиально новое?

Вообще-то, нет: все электронные чипы не безгрешны, и это не новость. RAM, SSD, сетевые адаптеры – везде довольно существенная вероятность потери и/или искажения данных при передаче и хранении. По разным причинам – от космического излучения, до тех же дефектов производства5.

Можно вспомнить row hammer attack – где речь идет даже не о дефекте производства, а о нестандартном режиме использования DRAM, в котором ток утечки оказывается выше расчетного.

Меня, как физика, всегда удивляло, насколько хорошо инженерам удается эмулировать дискретную логику поверх непрерывных физических систем. Ведь физические системы эволюционируют во времени непрерывно – законы физики выражаются непрерывными уравнениями. Интересно и нетривиально, что физическую систему вообще можно так аккуратно выстроить, что ее внешнее поведение выглядит как дискретное.

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

Но если сталкиваешься с поразительным каждый день по работе, со временем смиряешься, и отвыкаешь поражаться. И только когда оказывается, что реальная непрерывная физика все-таки просачивается сквозь абстракцию дискретной логики – только тогда снова задумываешься: а как же, блин, оно вообще все эти годы работало?

Но RAM, SSD, и сетевые адаптеры хотя бы функционально просты. Физическая реализация может быть очень изощренной, но функционально они все реализуют очень простой протокол: "что положил – то и возьмешь". Что в сеть отправил – то на другом конце должен получить. Из-за простого функционального протокола их гораздо проще тестировать на производстве, а на стадии эксплуатации с ошибками можно справляться сравнительно простыми и не слишком дорогими методами, типа контрольных сумм, и кодирования с коррекцией ошибок.

А процессоры функционально сложны, тестировать их гораздо тяжелее. И придумать какой-то аналог CRC/ECC для всех видов вычислений в современном процессоре – тоже сложно (хотя кто-то, вроде, пытается). В принципе, тройное резервирование с голосованием решает проблему – но это слишком дорого для использования почти везде, кроме авиации и космонавтики.

Что с этим делать?

Конечно, производителям нужно улучшать техконтроль. Но вряд ли это позволит решить проблему полностью. Современные чипы все сложнее, в них все больше специализированных блоков для конкретных видов вычислений (математические сопроцессоры, векторные операции, GPU, neural engine…), а текущие технологии производства близки к пределу своих возможностей. Так что возможных вариантов непредусмотренных взаимодействий между частями разных блоков будет становиться только больше, и сомнительно, что производителям удастся протестировать их все.

Плюс к тому некоторые дефекты проявляются только с возрастом, и такие дефекты особенно сложно отсеять техконтролем на выходе с конвейера.

То есть весьма вероятно, что доля "тихих" дефектов в железе будет возрастать. И это значит, что нам, разработчикам, придется все чаще иметь в виду, что железо может давать неправильный результат.

В целом, это напоминает ситуацию с многопоточным программированием в 2000-х: большинство разработчиков тогда клали болт на тонкости моделей памяти, потому что ошибки многопоточности довольно редко себя проявляли в тех условиях и на типичных парках машин того времени. Я помню презентацию Яндекса года 2010 примерно, где автор показывал, что код с вероятностью ошибки 1е-9 создаст проблему Яндексу уже в течении нескольких дней, потому что у Яндекса этот код исполняется на 1000 серверов 24/7 – а конторе Рога-и-Копыта, возможно, не создаст проблем никогда, потому что у них 3 сервера загруженные на 10% в рабочее время по будням.

Прошло 10-15 лет, и теперь уже даже у Рогов с Копытами – десятки серверов с сотнями ядер, и позволить себе игнорировать ошибки многопоточности не могут даже они.

Не исключено, что и эти дефекты железа, которые сейчас волнуют только гугл да фейсбук, через 10 лет будут волновать всех нас. Хотя это не точно.

Философские мысли

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

Поначалу, когда смотришь на биологические системы с позиции инженера, кажется – мрак и ужас, все переплетено и перепутано, неэффективно, никаких границ абстракций, едва ли есть модульность, и вообще – нормальный инженер сделал бы гораздо лучше ("какой плохой оптик господь бог, я бы построил глаз в 100 раз лучше").

Но чем сложнее становятся инженерные системы, тем чаще оказывается, что вся эта стройность, модульность, абстракции – это luxury, на которые можно полагаться пока достаточно далек от технологических пределов. А как к пределам приближаешься – так уже не до жиру.

В частности, чем ближе мы приближаемся к технологическим пределам – тем чаще размываются (приходится размывать) границы абстракций.

Например, идея mechanical sympathy, которую еще 10 назад популяризовал Мартин Томпсон – как раз про то, что нельзя создавать высокопроизводительный код ориентируясь на абстракцию идеального процессора, не заглядывая под капот реальной и конкретной процессорной архитектуры.

Или – все чаще приходится слышать "every system is a distributed system". Это тоже про размывание границ абстракций: можно работать в рамках абстракции "точечной" системы, но за поддержание этой абстракции приходится платить. И чем дальше, тем чаще и больше можно выиграть, если эту абстракцию отодвинуть, и работать с более реальной моделью системы – размазанной в реальном физическом пространстве, с физически ограниченной максимальной скоростью распространения сигналов.

И если принять, что дефекты в электронике это данность, с которой придется жить – значит, еще от одной абстракции придется потихоньку отказываться. Придется говорить, что every system is a distributed bizantine fault tolerant system.

Интересно попробовать угадать, какая следующая абстракция начнет протекать. Я, как физик, предвзят: мне кажется, следующей потечет абстракция дискретной логики. Мне кажется, что повсеместное использование дискретной логики – это особенность текущего периода в истории. Просто повезло, что удалось найти технологии, позволяющие почти полвека бурно прогрессировать в эмуляции дискретной логики поверх аналоговых физических систем.

Возможно, что это везение уже закончилось – я не первый раз слышу, что не видно технологий, чтобы еще 50 лет так бурно прогрессировать. Возможно, чтобы прогрессировать дальше, придется в какой-то степени возвращаться к аналогу.

И даже видно, где аналоговый подход может себя хорошо показать – нейросети. Нейросети сильно избыточны, и довольно устойчивы к дефектам – биологические нейросети сохраняют функциональность при большом разбросе параметров отдельных элементов. Если регулярно дообучать сеть, то она способна до какой-то степени справляться и с переменными дефектами – например, с возрастной деградацией.

(Более того, насколько я понимаю, для нейросети дефекты вообще могут работать в плюс – обеспечивать своего рода регуляризацию, вынуждать процесс обучения сходиться к более шумо-устойчивому решению)

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

…И я вижу здесь аналогию с ролью математики в человеческом знании: мы используем математику чтобы проверять и уточнять свои интуитивные выводы – но и наоборот, мы используем физическую интуицию чтобы проверять вменяемость результатов сложных математических расчетов. Можно себе представить, как в будущем дискретные процессоры будут проверять и уточнять результаты аналоговых нейросетевых вычислений – а нейросети будут искать аномалии в поведении дискретных процессоров, чтобы вовремя отзывать подозрительные результаты, и выводить из эксплуатации дефектные экземпляры.

То есть было бы логично такое себе представлять – если предположить, что и дальше инженерные решения будут естественным образом все более "биологизироваться".

Примечания

  1. Доклад (~9 мин): https://www.youtube.com/watch?v=QMF3rqhjYuM, статья: Cores that don't count (Peter H. Hochschild и еще 6 авторов)

    Статью очень рекомендую прочитать: это всего 7 страниц, а уйма интересных мыслей и открытых вопросов. При этом все изложено очень лаконично – сомневаюсь, что статью можно пересказать короче, чем она есть. Определенно стоит получаса времени. Видео еще короче, но оно и менее интересно.

  2. Большинство наблюдаемых ошибок воспроизводятся регулярно, но вероятностно – не каждый раз, но в каком-то проценте случаев. Некоторые ошибки, которые они наблюдали, проявляются с повышением температуры процессора, или при каких-то специфических нагрузках (напоминает row hammer). Или проявляются по мере старения процессора – т.е. после какого-то времени эксплуатации.

  3. Точнее: для конкретного ядра процессора – соседние ядра обычно работают корректно.

  4. Silent Data Corruptions at Scale. Достоинство статьи от фейсбука – конкретный пример дефектного CPU с ошибкой возведения в степень.

    Но это единственное достоинство – в остальном, статья написана плохо: корявый язык, много воды и общих слов. Добрая половина статьи – нудное перечисление шагов, которые они сделали, чтобы от scala-кода добраться до ассемблера. Если читать, то по диагонали.

  5. Знаменитая статья того же гугла о статистике ошибок в оперативной памяти с/без ECC: DRAM Errors in the Wild: A Large-Scale Field Study

10 комментариев:

  1. мне кажется, что существующие софтверные системы автокоррекции железных ошибок прекрасно справляются и с этой проблемой тоже. нечетное количество (3) дублирующих active servers ответ пользователю посылается после получения кворумного количества (2) одинаковых ответов. сервер приславший отличный (от других) ответ - гасится. что-то не так с этой схемой?

    ОтветитьУдалить
    Ответы
    1. Так это и есть 3х-резервирование с голосованием. Справляются, да (пока есть уверенность, что /логика голосования/ не содержит дефектов :)

      Вопрос в цене -- трехкратное дублирование всех вычислений не каждый себе может позволить. Авиация, космонавтика, вероятно, автомобильные автопилоты -- да, конечно. В массе же -- вряд ли.

      Ни CRC, ни даже ECC -- для сравнения -- не требуют таких больших расходов.

      Удалить
    2. ...но надо еще учитывать, что 3х-кратное резервирование с голосованием работает в предположении, что ошибки -- это независимые случайные события. Вообще говоря, это не так: например, софтовые ошибки будут возникать во всех 3 вычислителях одновременно. Поэтому, как я понимаю, в аэрокосмосе по общей спеке 3 команды разрабатывают 3 /разных/ программы -- чтобы ошибки у них были в разных местах. Но даже это не всегда дает нужный результат: даже работая независимо, разработчики пользуются общими методами/паттернами работы, из-за чего ошибки даже у разных команд оказываются весьма похожими (у меня где-то в загашнике есть статья на эту тему).

      В случае с дефектами производства ситуация похожа: если уж какой-то дефект есть в одном экземпляре процессора, то вероятность, что в другом экземпляре этот или похожий дефект тоже будет -- выше, чем по модели независимых случайных величин.

      Т.е. трехкратное резервирование надо еще устраивать, например, из процессоров разных производителей.

      Удалить
    3. ecc/crc решают задачу лишь от части.. сбойнуть могут - процессор, память, сетевая карта, свитч... ну и не так дорого как кажется. кроме того ecc память как-то вот уж СИЛЬНО медленней не-ecc. и возможно мне везло, но я пока не видел систем которые одновременно требовали и гугловой масштабируемости и не-гугловой надежности :)

      Удалить
    4. ошибки в софте - этот подход не раешает, поэтому ... бывают еще followers, которые могут пропустить запросы на которых завалились leaders :) я бы скорей рассматривал ситуацию в разрезе - как можно существенно увеличить надежность системы без потери производительности. дальше клиент решает - готов он платить или нет

      Удалить
    5. >я пока не видел систем которые одновременно требовали и гугловой масштабируемости и не-гугловой надежности

      Так авторы отмечают, что /некоторые/ дефекты CPU будут компенсироваться теми же инструментами, которые уже используются для компенсации ошибок дисков и сети и т.п. А /некоторые/ -- нет. Даже в отказоустойчивых распределенных системах с большим резервированием обычно предполагается, что локально-исполняемый код не может тихо накосячить -- узел может упасть, но не может неправильно посчитать хэш блока.

      Т.е. в терминологии распределенных систем, есть fault tolerance, но не bizantine fault tolerance.

      Я, честно говоря, даже не знаю есть ли вообще хоть какая-то система, которая способна успешно отработать тихие ошибки (non-fail-stop) в самом алгоритме выбора majority vote, например.

      Удалить
  2. Спасибо за комментарии к оригинальной статье - любопытно был наткнуться на это в своей ленте, так как один из оригинальных кейсов для исследования был наш продакшен в GCP :) Выглядело как нестабильное FPU вычисление, только на одной из машин, и только на одном наборе данных - но для конкретных данных/машины воспроизводилось в 100% случаев. К счастью, результат вычислений был очевидно неправильным (на несколько порядков) и был отловлен автоматически

    ОтветитьУдалить
    Ответы
    1. О, это интересно. А у вас все результаты вычислений автоматически перепроверяются, или это был удачный случай? А то я, когда про свои системы думаю, с трудом могу оценить, насколько далеко мог бы утечь неправильный результат от места, где он получился.

      Удалить
    2. Автоматической перепроверки у нас нет, можно считать что 'повезло' заметить: у нас вместе с продакшен трафиком гоняется много тестов/регрессий на тех же машинах/гриде, и где-то через месяц после миграции в GCP один раз(!) сломался один (!) тест - но сломался так опасно, что было решено докопаться, в чем дело. Но в целом, чтобы такое поймать, нужны достаточно параноидальные проверки, придётся платить перформансом. Кажется гугл собирался делать burn-in для GCP машин, так что наверное имеет смысл оставить это на стороне провайдера инфраструктуры.

      Удалить
    3. Действительно, повезло. В каком-то смысле это можно считать идеей для best practice: периодически гонять регрессионные тесты на рабочих серверах.

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

      Удалить