Аппаратное Обеспечение На Службе Алгоритма



Борис Бабаян о прошлом, настоящем и будущем вычислительной техники

Аппаратное обеспечение на службе алгоритма

Как выглядит развитие компьютерных технологий для человека, который занимается разработкой компьютерных технологий более полувека? На эту тему мне удалось поговорить с Борисом Арташесовичем Бабаяном, директором по архитектуре компании Intel. Борис Бабаян известен как главный архитектор компьютерных систем «Эльбрус-1», «Эльбрус-2» и «Эльбрус-3».

Некоторые из его идей использованы в архитектуре Transmeta. В настоящее время Борис возглавляет разработку новой микропроцессорной архитектуры в Intel. Чтобы совсем избавиться от формальностей, перечислю звания, степени и должности Бориса: Член-корреспондент РАН, доктор технических наук, профессор, заведующий кафедрой микропроцессорных технологий МФТИ, Intel Fellow, лауреат Государственной и Ленинской премий.

Дальнейшее повествование строится с точки зрения Бабаяна.

Мои немногочисленные комментарии представлены в виде боковых панелей или ссылок на интернет-страницы.

Уместно спросить, о чем я буду говорить.

Ответ может показаться очень необычным: обо всем.

Обо всем, что делаю я и мои коллеги.

Я думал о проблемах моего текущего проекта и о том, что делать дальше.

И я глубоко почувствовал, что в нашем деле Все тесно связаны друг с другом.

И архитектура, и языки программирования, и операционная система.

Ну, всё, всё, всё вместе, понимаешь? Об этом и будет мой рассказ.

Когда я взглянул на всю ситуацию, меня это очень сильно поразило.

Похоже, что больше ничего аппаратно оптимизировать нельзя.

Я и мои коллеги знаем, что это не так.

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

И тем, кто суперскаляр занят, конец виден - делать больше нечего.

И все же, если рассматривать все развитие вычислительной техники, мы ближе к началу, чем к концу.

К сожалению, а может быть и к счастью, не знаю, вся эта история, мне кажется, имеет конец.

Но это, вероятно, видимый конец.

Я думаю, это конец.

А возможно, что и при других условиях.

Но это было что-то вроде предисловия.

В общем, тема моего разговора — история развития нашего бизнеса, всех компьютерных технологий, компьютерных технологий.

Попутно я буду говорить о роли наших российских учёных, советских учёных, что ли.

Но это не моя цель.

Это, так сказать, случайно.

К сожалению, в России об этом знают очень немногие.

Всё, это было последнее предисловие.

Теперь начнем.

Посмотрите: что такое компьютерные технологии? Это аппаратная реализация алгоритмов с использованием языков программирования.

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

Поэтому, если мы собираемся что-то анализировать, то в первую очередь нужно посмотреть на эти составляющие.

Начнем с алгоритмов.

Алгоритмы — это нечто абстрактное, нечто вечное.

Например, цифры.

Разных алгоритмов может быть много, и каждый из них вечен.

Как представлены алгоритмы? В них, как и во многих других вещах, связанных с реальным миром, можно выделить две составляющие: временную и пространственную.

Временная составляющая – это последовательность операций: что после чего выполняется.

Этот компонент чрезвычайно параллелен.

Конечно, существуют чисто последовательные алгоритмы, но в принципе понятие алгоритма — это понятие параллельной структуры.

Обычно граф вычислений очень параллелен и чрезвычайно структурирован.

Теперь пространственная составляющая.

Пространственная составляющая также параллельна и структурирована.

На что она похожа? Это объекты, над которыми работают операции.

Множество объектов.

Эти объекты могут ссылаться друг на друга и быть вложенными друг в друга.

Но их много и с ними работают разные операции.

Очень все параллельно.

Вот что такое алгоритмы.

А что насчет железа? А аппаратное обеспечение, в отличие от алгоритмов, не вечно.

Оно сильно меняется со временем.

Вначале железо было очень примитивным.

Когда я начинал.

- а я начинал в Физтехе, я поступил туда в 1951 году - так вот, на тот момент первый БЭСМ не работал.

Один бит информации тогда был представлен двумя электронными лампами.

Это кубический дециметр! Невероятный объём.

И исполнительное устройство было только одно.

Он занимал три комнаты.

Как я всегда шучу, перенос битов начался в одной комнате и закончился через две комнаты.

Это ужасный размер.

И посмотрите, что сейчас.

На одном чипе размещено невероятное количество исполнительных устройств.

Но БЭСМ-первый был далеко не первым.

Я не видел самых первых машин.

Например, Урал.

Это была строго последовательная машина.

Немного серийная машина.

То есть был магнитный барабан.

Информация считывалась с него побитно.

Затем считанные значения, например, суммировались и снова записывались по одному биту на барабан.

Ужасный.

Но необходимо было спроектировать такие машины.

Куда идти? Тогда не было возможности отразить на технике такое невероятное великолепие, как параллельность во времени и пространстве.

Просто даже говорить об этом было нечего.

Необходимо было упрощение.

Ну какое упрощение было бы естественным в данном случае? Линеаризуйте все! Превратите все в линию.

Это очень просто.

Превратить параллельный алгоритм в линейку ничего не стоит. Причём как в пространстве, так и во времени.

Так появились первые автомобили.

И это, конечно, блестящее решение.

Хотя… гениальным это назвать сложно, настолько это просто.

Но это эффективное решение для того времени.

Потому что превращение сложного алгоритма в линейку не требует никакой оптимизации.

Компилятору легко это сделать.

Правда, тогда мы еще никогда не слышали о компиляторах и языках программирования.

Все было запрограммировано по битам.

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

Они вообще не были учтены.

Программисты работали с тем, что им дали разработчики оборудования.

И программы были крошечными.

Поэтому писать битами было проще и эффективнее, чем на любом языке.

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

Моя любимая шутка в те времена была о том, что настоящие мужчины работают на языке ассемблера, а языки — это всего лишь баловство.

В отсутствие языков и компиляторов человек сам представлял алгоритм в виде линейки.

И это соответствовало некоему знакомому понятию времени.

Время последовательное — и алгоритм последовательный.

Это все естественно.

Поэтому компиляторам (к моменту их появления) было очень легко выполнить эту работу.

С автомобилем еще проще.

Линейная последовательность инструкций, в которую превратился алгоритм, выполнялась строго последовательно.

Для этого требуется очень простое оборудование! Тогда — а я тогда уже делал автомобили — нам даже в голову не пришло моделировать поведение техники.

В наше время без моделирования невозможно обойтись.

Современная архитектура очень динамична.

Без моделирования их оптимизировать невозможно.

А в ту эпоху время выполнения приложения равнялось сумме времен выполнения отдельных операций.

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

Никаких регистров и кэшей не было.

Первый BЭSM работал так: считывал одно число из памяти, второе число, выполнял операции и записывал обратно.

Чтение из памяти, по сравнению с операцией, было мгновенным.

Операции тогда заняли много циклов.

Пространство также было очень простым.

Объектов не было.

Это была просто последовательность битов.

О безопасности, т.е.

о защите процессов друг от друга речи не шло вообще.

Машина находилась в отдельной комнате.

У какого-то человека был ключ от этой комнаты — вот и вся безопасность.

Пришел программист, сел за станок и начал работать.

Закончив, он снял магнитную ленту, ушел, и пришла еще одна.

Все приносили и уносили с собой свои данные, а на машине работал только один процесс.

100% безопасность.

Жизнь программиста была непростой.

Каждая новая машина – это новая система управления.

Все программы были переписаны.

Единственным спасением было то, что программ было очень мало, поэтому переписывание можно было терпеть.

Это было начало.

Трагедия в том, что совместимость с этим началом мы имеем и по сей день.

Все современные системы управления линейны.

Хотя оборудование сейчас очень параллельное.

И это очень плохо.

Это усложняет программирование.

Возникает много ошибок.

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

Ужасный! Но это не все.

От первых личных автомобилей мы унаследовали шины.

Аппаратное обеспечение в то время еще не было параллельным, и процессоры имели только один исполнительный блок.

Но сами процессоры уже могли работать параллельно друг с другом на общей памяти.

Это именно то, для чего им нужна была шина.

Шина создала строгий порядок всех обращений к памяти всеми процессорами.

То, что сейчас называется моделью сильного порядка или памяти.

Программистам дали такую систему, и они поняли, что все вовремя заказано.

Программисты, как всегда, просто использовали то, что им давали.

И вот что им дали.

Тогда синхронизация через семафоры и чтение данных из памяти заняли одинаковое время.

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

В результате программы писались бессистемно.

А дальше ситуация только ухудшилась.

Кэши появились.

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

Потому что доступ к данным стал намного быстрее, чем доступ к семафору.

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

Использовать семафоры стало очень невыгодно.

Отсюда и возникли проблемы совместимости.

Теперь шины уже давно нет. Однако все автомобили моделируют одну и ту же шину, которая была в самых первых автомобилях.

Конечно, его немного изменили.

Разработчики П6 Мы увидели, что если строго выполнять упорядочение памяти, то теряется 25% производительности.

Поэтому они ввели одно облегчение: чтение из памяти может опережать запись в память.

Но тем не менее, чтение не может обогнать друг друга, запись не может обогнать друг друга, а запись не может обогнать чтение.

Или можно было бы все отменить и сделать заново.

Мы в Элбрусах никогда не пользовался шинами.

У нас с самого начала была перекладина.

Крестовой переключатель Прямая связь между каждым процессором и каждым Итак: юмор в том, что первые автомобили еще моделируются.

И не только в железе, но и в языках программирования.

Все языки программирования сломаны.

Они очень далеки от алгоритмов — от того, что я назвал параллельным временем и параллельным пространством.

Они ближе к самым первым машинам, где все последовательно.

Мы видим, что совместимость держит все мертвой хваткой, и изменить это очень сложно.

Теперь отдельно рассмотрим, как развивалась временная составляющая и как развивалась пространственная составляющая.

Ну, начнем с пространственной составляющей.

Это намного проще.

Хотя временная составляющая может быть более актуальной.

Но это сложнее.

Итак, пространственный.

С ним все очень просто.

Это объекты.

Это означает, что машина должна работать с объектами.

Когда мы запускали первый флюрус, мы не думали о безопасности.

Безопасность.

Защита процессов друг от друга могла бы стать мотивацией для введения всего того, что обсуждается ниже.

Вот почему здесь упоминается безопасность Как я уже сказал, проблем с безопасностью тогда не было.

Мы взялись за объекты для поддержки языков высокого уровня.

Мы тогда задумались: каким должен быть язык высокого уровня? В то время, в 1972 году, считалось, что программирование высокого уровня обеспечивают такие языки, как Алгол и Фортран.

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

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

Это нонсенс! Замечу, что на тот момент уже были машины с поддержкой языков высокого уровня.

Например, компания Берроуз выпустил автомобиль, который выполнял Расширенный Алгол .

Типы данных там реализовывались через теги, которые хранились в памяти вместе с данными.

Это была хорошая идея, и мы позаимствовали ее у Берроуза.

Но то, как они использовали эти теги, было просто недоразумением.

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

Работало это следующим образом: каждой используемой ячейке памяти жестко присваивался определенный тип.

Эта информация использовалась для автоматического преобразования данных во время их записи в память.

Если, например, действительное число было сохранено в ячейке памяти, помеченной целым числом, машина динамически преобразовывала бы действительное число в целое число перед выполнением записи.

Поддерживая существующие статические языки, Берроуз, по сути, поддерживал старое оборудование, потому что именно для этого были созданы статические языки.

Это просто глупо! Берроуз, разрабатывая новую архитектуру, в конечном итоге сосредоточился на старых автомобилях.

Кроме того, теги можно было менять на лету в непривилегированном режиме, что тоже очень глупо.

Однако справедливости ради следует отметить, что динамическое приведение типов было предоставлено Берроузу практически бесплатно.

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

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

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

Такое дополнительное чтение кажется ужасной тратой.

Но дело в том, что тогда его использовали торическая память .

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

А размагничивание производилось через чтение.

Таким образом, чтение типа ячейки во время записи не приводило к дополнительным накладным расходам.

Его просто совместили с размагничиванием.

Но вернемся к Эльбрусу.

Мы отказались от фокуса на старых языках.

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

Это объектная ориентация.

Вот как работают алгоритмы? Представим, что выполняется некий алгоритм.

Если он генерирует новый объект, ему не нужны никакие биты.

Объект, ну, появляется в пространстве или типа того.

Доступ к этому вновь созданному объекту возможен только с помощью текущего алгоритма.

Больше о нем никто просто даже не знает. Потому что оно было сгенерировано по определенному алгоритму.

Абстрактный алгоритм, а вовсе не аппаратный, понимаете? Это должно как-то поддерживаться аппаратно.

Далее, каждый объект имеет тип.

Это означает, что мы также должны поддерживать типы.

Сначала мы пытались применить весьма экстремистский подход: в тегах записывались целые числа, настоящие.

Но потом мы увидели, что это совершенно не нужно.

Нет необходимости поддерживать какие-либо типы в тегах.

И вот почему.

Немного о системе типа «Эльбрус-1» Рядом с пользовательскими данными в памяти хранилась информация о их типе.

Эта же информация поступала в регистры при чтении данных из памяти.

Знание типа позволяло контролировать операции, которые можно было выполнять над объектами.

Например, попытка выполнить целочисленное сложение действительных чисел привела к сбою.

Представьте, что вы берете действительное число и хотите изменить в нем некоторые биты.

Например, вы хотите что-то сделать с экспонентой.

Если поддерживается строго все многообразие типов (множественное, вещественное, целое,.

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

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

Рабочий буквально Те.

через набор битов Хочу сказать, что проверить его семантику внутри процедуры невозможно.

Аппаратное обеспечение не может знать семантику.

Ответственность за ошибки в процедуре лежит на программисте.

Нет необходимости защищать программиста внутри процедуры.

Если он захочет, он всегда может там ошибиться.

Другое дело — межпроцедурные отношения.

Межпроцедурные отношения регулируются указателями.

А указатели, вообще говоря, нельзя менять буквально.

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

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

Это первый.

Второй.

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

Это если мы хотим иметь универсальный язык.

Для меня тогда — напомню, это был 1972 год — универсализм означал, что на этом языке можно эффективно написать операционную систему.

Если операционная система не программируется, то подход не является универсальным.

Чтобы написать операционную систему, типы данных должны быть динамическими.

Динамические типы Подход, при котором передача данных не сопровождается проверкой типов.

На уровне языка это проявляется, например, в том, что любой переменной можно присвоить объект любого типа.

Весь типовой контроль передается на стадию исполнения Почему это так? Допустим, вы определяете имя и статически привязываете к этому имени тип.

В вашей программе вы знаете этот тип, но операционная система, работая с вашими данными, не знает, как они описаны в исходном языке.

Если в программе переменная статически описана как целое число, операционная система об этом не узнает. Она видит только двоичные коды.

Поэтому статический подход совершенно неприемлем.

Кроме того, это еще и не удобно.

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

Это совершенно естественно.

Но статический подход этого не позволяет, в отличие от динамического.

В результате мы пришли к выводу, что язык высокого уровня — это динамический язык со строгим контролем указателей.

Никлаус Вирт пришел именно к такому выводу, практически независимо – мы мало общались и почти не читали друг друга.

Это человек номер один в языках.

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

Вирт создал типодинамический язык под названием Эyler. Он был невероятно интересен.

Все были просто в восторге от этого языка.

Но ему не хватало эффективности.

Потому что это не поддерживалось аппаратно.

Было много динамического контроля.

Тогда Вирт отступил.

Он сказал: да, типы должны быть, но пусть они будут статичными.

И контроль должен быть.

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

Например, если у вас есть указатель на массив, то никто не сможет, имея этот указатель, выйти за границы массива.

Это невозможно.

И что произошло в результате? Мы создали настоящий язык.

У нас были метки.

То есть ко всем данным добавлялось несколько цифр, описывающих тип.

Мы сделали управление указателем.

Одним словом, мы создали Эл-76 .

Это покойный Володя Пентковский делал.

Он тогда был программистом.

Операционная система Llbrus была написана на самолете Эl-76. Серёжа Семенихин это уже сделал.

26 человек в середине 70-х создали операционную систему: мультипрограммную, мультипроцессорную, мультитерминальную.

В то время пакетный режим в основном использовался повсеместно.

А у нас такая развитая операционная система! Кроме того, наш стандартный подход значительно упростил программирование.

Это даже увеличило производительность.

Мы сделали три поколения машины, используя такой подход: первое, второе, третье? Наши машины использовались в Очень ответственные системы.

Противоракетная оборона Москвы, контроль над космосом, ядерные проекты в Арзамасе.

При этом все наши пользователи говорили: отладка на этой машине происходит в 10 раз быстрее, чем на старых машинах.

Создавалось впечатление, будто ты работаешь с постоянно включенной системой отладки.

И без потери эффективности.

Когда наши ребята получили западные станки - в начале 90-х - они стали подходить ко мне и говорить: как можно на этих станках работать? На них нельзя отлаживать программы.

Ужасный! Теперь посмотрите, что случилось с этим подходом! Исторически.

Мы выпустили первую машину в 78 году.

Параллельно я прошел первый тест по операционной системе.

До 82-83 годов в нашей стране широко использовались Первые фунты.

Примерно в то же время многие университеты по всему миру проводили исследования в области типовой безопасности.

И Intel тоже заинтересована в таком подходе.

Ещё сделали машину типа безопасности, 432-й .

Спросите любого пользователя Intel, знает ли он, что у Intel есть 432-я машина в истории.

Ответ будет: нет, он не знает. Об этом стыдно вспоминать! Просто позорная машина.

Это обеспечивало безопасность типов.

Но были элементарные ошибки.

В 432 реализована защита указателей, что, конечно, очень правильно.

Однако все указатели хранились в отдельном сегменте.

Это называлось справочной таблицей программ.

Машина контролировала, чтобы в этом сегменте могли находиться только указатели.

И больше нигде, кроме него, никаких знаков быть не могло.

Я читал их статьи.

Говорят, всё это очень круто, но держать указатели в отдельном сегменте очень неудобно.

Указатели должны отправляться как обычные данные.

Вот что мы сделали.

Наши указатели — это просто данные.

А 432-й вынес знаки в отдельный сегмент. Это привело к ужасным результатам.

Например, для индексации массива требовалась трехадресная операция.

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

И два сегмента для локальных данных: тоже указательный и скалярный.

ЦК И Совет Министров Потом скопировали западные машины, а с появлением 432-го среди учёных распространилась статья: смотрите, нам нужно скопировать эту машину.

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

Сначала его возглавил Фильцев.

А потом я написал большую возку против Intel. Он написал, что машина плохая и через несколько месяцев выйдет из строя.

И она потерпела неудачу.

Когда я пришел в Intel, я нашел статью Боб Колвелл , того гениального человека, который создал P6. Он проанализировал 432-ю машину и пришел к тому же выводу, что и я: идея колоссальная, но реализация паршивая.

В статье Колвелла есть конкретные цифры.

Например, вход в процедуру требовал до пятидесяти обращений к памяти.

Как можно было работать на такой машине? Как я уже говорил, 432-й прожил недолго.

Но что случилось с безопасностью типов после этого? В каких направлениях начали развиваться языки и техника?



Продолжение должен.

Автор благодарит Андрея Доброва, Александра Кима, Дмитрия Масленникова и Александра Останевича за помощь в подготовке материала.

Теги: #Компьютерное оборудование #Процессоры #Intel #программирование #История ИТ #железо #Эльбрус #микропроцессоры #история компьютерной техники #типовая безопасность #Борис Бабаян

Вместе с данным постом часто просматривают: