Автор книги: Брайан Керниган
Жанр: Компьютеры: прочее, Компьютеры
сообщить о неприемлемом содержимом
До сих пор я уклонялся от ответа на вопрос о том, как инструкции и данные представлены в памяти. Как это работает?
Вот одно из возможных объяснений. Предположим, что каждая инструкция использует одну ячейку памяти для хранения своего цифрового кода, а также задействует ту, что расположена рядом, если ссылается на местоположение в памяти или имеет значение данных. То есть GET занимает одно место, а инструкции вроде IFZERO и ADD, которые ссылаются на ячейку памяти, используют два. Второе – это место, на которое они ссылаются.
Предположим также, что любое значение данных помещается в одной ячейке. Это все упрощения, однако они не слишком искажают картину того, что происходит в реальных компьютерах. Наконец, примем, что числовые значения инструкций следующие: GET = 1, PRINT =2, STORE = 3, LOAD = 4, ADD = 5, STOP = 6, GOTO = 7, IFZERO = 8. В таком порядке они появлялись на предыдущих страницах.
Программа на рис. 3.8 суммирует последовательность чисел. Когда программа начинает работать, содержимое памяти будет таким, как показано на рис. 3.9. Здесь также изображены фактические ячейки памяти, три привязанные к ним метки, инструкции и адреса, соответствующие содержимому памяти.

Рис. 3.9. Как программа сложения чисел выглядит в памяти
Симулятор Игрушки написан на JavaScript – языке программирования (ЯП), о котором пойдет речь в главе 7, – но мы могли выбрать любой другой ЯП. Данный симулятор легко расширить. Например, вы без труда добавите инструкцию умножения или условную ветвь другого типа, даже если никогда раньше не видели компьютерную программу. Это хороший способ проверить, как вы усвоили материал. Код можно найти на веб-сайте этой книги.
3.2. Настоящие процессорыМы рассмотрели упрощенную версию процессора, но он не сильно отличается от тех, что стояли в ранних вычислительных устройствах или сейчас применяются в маленьких. Современные ЦПУ гораздо сложнее в деталях, и все сосредоточено вокруг производительности.
Любой процессор снова и снова производит цикл извлечения, декодирования, выполнения. Он извлекает из памяти очередную инструкцию, которая обычно хранится в следующей ячейке памяти, но ее местоположение также могли задать GOTO или IFZERO. Процессор декодирует инструкцию (то есть выясняет, что она делает) и совершает все необходимые приготовления для ее запуска. Затем он выполняет инструкцию: вытаскивает информацию из памяти, производит арифметические или логические действия и сохраняет результат в подходящей комбинации битов. Потом ЦПУ возвращается к шагу извлечения. Цикл «извлечение – декодирование – выполнение» в настоящем процессоре задействует хитроумные методы, которые ускоряют всю процедуру, но фундаментально там нет разницы с циклом для сложения чисел, показанным выше.
Настоящие компьютеры выполняют больше инструкций, чем наша Игрушка, хотя они относятся к тем же основным видам. Они знают больше способов того, как перемещать данные, выполнять арифметические действия (в том числе для различных размеров и типов чисел), сравнивать и разветвлять, а также управлять остальными частями машины. Типичное ЦПУ имеет от пары десятков до пары сотен различных инструкций, которые вместе с данными занимают несколько ячеек памяти, обычно от 2 до 8 байт на каждую. В реальном процессоре есть много накопителей, чаще всего от 16 до 32. Поэтому он может хранить более одного промежуточного результата в своей, скажем так, чрезвычайно быстродействующей памяти.
Настоящие программы колоссальны по сравнению с нашими примерами для Игрушки, и часто в них содержатся миллионы инструкций. Мы еще вернемся к тому, как пишутся программы, когда будем говорить о ПО в последующих главах.
Дисциплина, которая занимается разработкой процессора и его связей с остальными частями машины, называется архитектурой ЭВМ. В университетах ее часто изучают как подобласть на границе информатики и электротехники.
Одна из проблем, рассматриваемых архитектурой ЭВМ, – размер набора инструкций, то есть совокупности команд, которые выполняет процессор. Что лучше: множество инструкций для широкого спектра различных вычислений или небольшое количество команд – таких, которые проще создавать и которые будут выполняться быстрее? Разработка архитектуры предполагает поиск многогранного баланса функциональности, скорости, сложности, энергопотребления и программируемости. Снова процитируем фон Неймана: «В общем внутренняя структура арифметического устройства определяется компромиссом между стремлением к быстроте работы <…> и к простоте или дешевизне машины».
Как процессор соединяется с оперативной памятью и остальными частями компьютера? Начнем с того, что ЦПУ действуют очень быстро, выполняя одну инструкцию менее чем за наносекунду. (Напомним, что «нано» – это одна миллиардная, или 10“9.) Для сравнения, память чрезвычайно медленная: извлечение данных или инструкций из нее занимает от 10 до 20 наносекунд. Конечно, это молниеносно в абсолютном выражении, но неторопливо по меркам функционирования процессора. Он мог бы выполнить десятки инструкций за то время, что ему приходится ждать поступления данных.
В современных компьютерах для хранения недавно использованных инструкций и данных используется небольшое количество высокоскоростной памяти между ЦПУ и ОЗУ Она называется кэшем. Информацию, которую можно найти в кэше, быстрее достать оттуда, чем дожидаться ее извлечения из оперативной памяти. Подробнее о кэшах и кэшировании я расскажу в следующем разделе.
У разработчиков также есть набор конструкционных приемов, которые ускоряют работу процессора. ЦПУ можно изготовить так, чтобы шаги извлечения и выполнения совмещались, и тогда процессор будет одномоментно прогонять несколько инструкций на разных стадиях завершенности. Это называется конвейерной обработкой, как при движении деталей автомобиля по сборочной линии. Хотя выполнение любой отдельной инструкции будет занимать такое же время, при одновременной обработке других возрастут общие темпы выполнения. Иной вариант – параллельно прогонять несколько инструкций, если они не мешают друг другу или не взаимозависимы. В машиностроении тоже есть аналогия, параллельные линии сборки. Иногда инструкции даже можно выполнять не по порядку, если они не взаимодействуют.
Еще один вариант – одновременная работа нескольких процессоров. Сегодня это норма для ноутбуков и мобильных телефонов. В процессоре Intel моего компьютера 2015 года выпуска, на котором я сейчас печатаю, есть два ядра на одном чипе интегральной схемы. Сейчас наблюдается сильная тенденция в сторону увеличения количества ядер ЦПУ на чипе, а также на установку более одного чипа в устройстве. Поскольку размеры элементов интегральной схемы уменьшаются, на микросхему удается поместить больше транзисторов, и они, как правило, используются для того, чтобы добавить ядер и увеличить кэш-память. Процессоры сами по себе не ускоряются, но ядер становится больше, и фактическая быстрота вычислений продолжает расти.
Когда определяется, где будет применяться ЦПУ, в его конструкцию вносят еще ряд компромиссных решений. Долгое время их в основном изготавливали для настольных компьютеров, обладающих сравнительным изобилием доступной электрической мощности и свободного пространства. Благодаря этому разработчики могли сосредоточиться на создании как можно более быстрого процессора, зная, что тому вполне хватит и энергии, и возможностей отводить тепло с помощью вентиляторов. Из-за ноутбуков искомый баланс значительно изменился, так как пространство в них ограниченно, а при отключении от сети они получают питание от тяжелой и дорогой батареи. При прочих равных условиях процессоры для ноутбуков обычно работают медленнее и потребляют меньше электроэнергии.
В случае сотовых телефонов, планшетов и других портативных устройств требуется идти на еще большие компромиссы, поскольку размер, вес и мощность уменьшаются еще заметнее. Здесь уже недостаточно только «подкрутить» конструкцию. Если Intel и ее основной конкурент AMD – главные поставщики ЦПУ для компьютеров и ноутбуков, то в большинстве сотовых телефонов и планшетов используется процессор под названием ARM, специально спроектированный для работы с низким энергопотреблением. Структура таких ЦПУ запатентована английской компанией Arm Holdings.
Сравнение скоростей процессоров – дело сложное и, по сути, бессмысленное. Даже базовые операции вроде арифметических действий могут выполняться настолько разными способами, что трудно провести прямое сопоставление. Например, одному процессору понадобится выполнить три инструкции, чтобы сложить два числа и сохранить результат в ходе третьей, как делала Игрушка. Другому для такого вычисления хватит двух команд, а третьему – всего одной. Некоторые ЦПУ способны параллельно обрабатывать несколько инструкций или совмещать их, чтобы они выполнялись поэтапно. Процессоры умеют жертвовать скоростью работы ради снижения энергопотребления и даже динамически регулировать ее в зависимости от того, поступает энергия из батареи или из сети. В отдельные ЦПУ встроены как быстрые, так и медленные ядра для выполнения разных задач. Поэтому вам следует с осторожностью заявлять о том, что один процессор «шустрее» другого, – вероятно, ваша оценка субъективна.
3.3. КэшированиеСоответственно, мы обязаны признать возможность создания иерархических отделов памяти, каждый из которых будет обладать большей емкостью, чем предыдущий, но менее быстрым доступом.
Артур У. Бёркс, Герман Х. Голдстайн, Джон фон Нейман.Предварительное рассмотрение логического устройства электронного вычислительного прибора, 1946
Здесь стоит ненадолго отойти от темы и рассмотреть кэширование – идею, широко применимую за пределами вычислений как таковых. В процессоре кэш — это маленькая быстрая память, где хранится недавно обработанная информация. Тем самым удается избежать постоянных обращений к оперативной памяти, которая больше по объему, но действует значительно медленнее. Как правило, процессор неоднократно обращается к группам данных и инструкций за короткий отрезок времени. Например, пять инструкций в цикле программы, приведенной на рис. 3.9, будут выполняться по одному разу для каждого введенного числа. Если хранить их в кэше, то извлекать их из ОЗУ для каждого цикла уже не понадобится, и тогда программа начнет выполняться быстрее, поскольку для обработки инструкций не придется ждать их поступления из памяти. Аналогично, если держать Sum (переменную из программы для Игрушки) в кэше данных, доступ тоже ускорится, однако узкое место в этой программе – получение данных.
Типичный процессор имеет два или три кэша, которые последовательно увеличиваются по емкости и уменьшаются в скорости. Их часто называют уровнями LI, L2 и L3. Самый большой из них способен вмещать несколько мегабайт данных. (На моем ноутбуке 256 Кб кэша L2 для каждого ядра и 4 Мб в одном кэше L3.) Кэширование приносит пользу, так как велика вероятность, что недавно использованная информация вскоре понадобится вновь, а наличие ее в кэше уменьшит время ожидания отклика памяти. Обычно в процессе кэширования одновременно загружаются все блоки данных – например, блок последовательных ячеек памяти, когда запрашивается один байт. Это связано с тем, что «примыкающая» информация, вероятно, также скоро будет использоваться – и значит, почти наверняка уже окажется в кэше, когда в ней возникнет надобность. Тогда ссылкам на соседние данные не придется ждать.
Такой тип кэширования в основном невидим для пользователей, если не считать того, что оно улучшает производительность. Однако кэширование – гораздо более общая концепция, которая помогает нам независимо от того, используем ли мы что-то в данный момент и, вероятно, вскоре задействуем это же снова, или нам с большой вероятностью понадобятся соседние данные. Многочисленные накопители в процессоре, по сути, форма кэша на максимальной скорости работы. Оперативная память может служить кэшем для дисков, а ОЗУ и «винты» вместе – кэшем для данных, поступающих из сети. Наконец, сети часто имеют свои кэши для ускорения потока информации от удаленных серверов, где также есть кэши.
Возможно, раньше вы видели это слово в контексте «почистить кэш» для веб-браузера. Он сохраняет локальные копии изображений и других сравнительно объемных материалов, которые составляют веб-страницу, так как при повторном посещении страницы быстрее будет использовать эти копии, чем загружать все заново. Кэш не может расти бесконечно, поэтому браузер либо сам незаметно удаляет старые данные и освобождает место для новых, либо предлагает сделать это вам.
Иногда преимущества кэширования вполне очевидны. Запустите какую-нибудь объемную программу вроде Word или Firefox и замерьте время, которое понадобится ей для полной загрузки с диска. Потом закройте ее и немедленно перезапустите. Обычно во второй раз программа стартует намного быстрее, потому что ее инструкции все еще находятся в ОЗУ, которая играет роль кэша для жесткого диска. В дальнейшем, пока вы будете работать в других приложениях, память начнет заполняться их инструкциями и данными. Они «вытеснят» предыдущую программу из кэша.
Еще одна форма кэширования – список недавних файлов в таких приложениях, как Word или Excel. Word запоминает документы, с которыми вы работали в последнее время, и отображает их названия в меню, поэтому вам не нужно искать их каждый раз. По мере того как вы открываете новые файлы, те, к которым вы не обращались долгое время, будут заменены в списке на более свежие.
3.4. Другие виды вычислительных устройствДовольно просто решить, что все компьютеры – это ноутбуки, поскольку именно их мы видим чаще всего. Но существуют и другие разновидности вычислительных устройств, больших и маленьких, которые объединены тем, что способны производить одни и те же логические операции. Они имеют схожую архитектуру, но в них соблюдается различный баланс стоимости, мощности, величины, быстродействия и так далее.
Мобильные телефоны и планшеты – тоже вычислительные машины, которые управляются теми или иными ОС и формируют богатую компьютерную среду. Системы еще меньших размеров встроены почти во все цифровые устройства, которые загромождают нашу жизнь: фотоаппараты, электронные «читалки», фитнес-трекеры, бытовую технику, игровые консоли и так далее. Так называемый интернет вещей – сетевые термостаты, камеры безопасности, умные светильники, устройства распознавания голоса и тому подобное – также опирается на аналогичные процессоры.
В суперкомпьютерах, как правило, устанавливают большое количество ЦПУ и громадный объем памяти. Сами их процессоры порой имеют инструкции, которые обрабатывают определенные виды данных намного быстрее, чем их более привычные собратья. Правда, современные суперкомпьютеры основаны на кластерах быстрых, но в целом обычных процессоров, а не на специализированном оборудовании. Каждые полгода на вебсайте top500.org публикуется новый список 500 самых быстрых компьютеров в мире. Поразительно, как быстро повышается максимальная скорость: машины, которые находились в первой десятке несколько лет назад, сегодня вообще отсутствуют в списке. Лучшая машина на ноябрь 2020 года, построенная компанией Fujitsu в Японии, имеет 7,6 миллиона ядер и может выполнять максимум 537 × 1015 арифметических операций в секунду[20]20
На конец сентября 2023 года первое место в списке занимал суперкомпьютер Frontier (США, Hewlett-Packard) с 8,7 миллиона ядер и пиковым быстродействием в 1679 петафлопов.
[Закрыть]. Скорость суперкомпьютеров измеряется количеством операций с плавающей запятой, или флопами, т. е. количеством арифметических операций с числами с дробной долей в секунду. Лидер списка top500.org показывает результат в 537 петафлопов, а компьютер на 500-м месте – 2,4 петафлопа.
Графический процессор (GPU) – это специализированный процессор, который выполняет определенные графические вычисления намного быстрее, чем ЦПУ общего назначения. Такие устройства изначально разрабатывались для высокоскоростных расчетов графики, необходимой для игр, но они также применяются для обработки речи и сигналов в телефонах. GPU помогают ускорить работу обычных ЦПУ при определенных видах рабочих нагрузок. Графические процессоры могут параллельно выполнять большое количество простых арифметических вычислений, поэтому если какую-либо часть задачи можно передать для выполнения в GPU, то операция в целом будет выполняться быстрее. Данные устройства особенно полезны для машинного обучения (глава 12), при котором одни и те же вычисления производятся независимо в разных частях большого набора данных.
Распределенные вычисления выполняются на компьютерах, которые более независимы: они, например, не используют общую память, а иногда физически рассредоточены, вплоть до того, что находятся в разных частях света. Из-за такого подхода повышается вероятность того, что связь станет узким местом, но он позволяет людям и компьютерам взаимодействовать на больших расстояниях. Крупномасштабные веб-сервисы – поисковые системы, интернет-магазины, социальные сети и облачная обработка данных в целом – это распределенные вычислительные системы, в которых тысячи ЭВМ объединяются, чтобы быстрее получить результат для большого количества пользователей.
Все эти типы компьютеров базируются на одних и тех же фундаментальных принципах. Они основаны на процессоре общего назначения, который можно запрограммировать для выполнения бесконечно разнообразных задач. Каждый ЦПУ имеет ограниченный набор простых инструкций для выполнения арифметических действий, сравнения значений данных и выбора следующей инструкции на основании результатов предыдущих вычислений. Определяющая архитектура ЭВМ не сильно изменилась с конца 1940-х годов, но их физическая конструкция непрерывно эволюционировала поразительными темпами.
Возможно, это прозвучит неожиданно, но все упомянутые компьютеры обладают одинаковыми логическими возможностями и способны «обсчитывать» буквально одно и то же, если оставить в стороне такие практические факторы, как требования к скорости и памяти. Данную теорию независимо друг от друга доказали в 1930-х годах несколько ученых, включая английского математика Алана Тьюринга. Именно его подход легче всего понять неспециалисту. Тьюринг описал элементарное счетное устройство, гораздо проще нашей Игрушки, и показал, что оно может вычислить всё, что поддается вычислениям в самом общем смысле. Сегодня такой компьютер называется машиной Тьюринга29. Затем Алан показал, как создать машину Тьюринга, которая способна действовать как симулятор других подобных машин. Теперь такое устройство обозначается как универсальная машина Тьюринга (УМТ). Составить программу, которая будет имитировать УМТ, несложно. Также возможно (но уже не просто) написать программу для УМТ, которая будет имитировать настоящий компьютер. Следовательно, все компьютеры равны в том, что они умеют вычислять, но различаются в скорости обработки.
Во время Второй мировой войны Алан перешел от теории к практике: он сыграл главную роль в разработке специализированного компьютера для дешифрирования немецких военных сообщений30, о чем мы еще кратко поговорим в главе 13. Работы Тьюринга на благо фронта показаны – со значительными художественными отступлениями – в нескольких фильмах, в частности «Взлом кода» (Breaking The Code, телеканал ВВС) 1996 года и «Игра в имитацию» 2014 года.
В 1950 году Тьюринг опубликовал статью под названием «Вычислительные машины и разум»31, в которой предлагался тест (сегодня называемый тестом Тьюринга), который подошел бы для оценки того, демонстрирует ли компьютер человеческий интеллект. Представьте себе, как вычислительная машина и человек по отдельности общаются через клавиатуру и экран с человеком-опросчиком. Ведя такую беседу, может ли опрашивающий установить, кто из его собеседников – человек, а кто – компьютер? Тьюринг полагал, что, если их не удастся надежно различить, значит, ЭВМ демонстрирует разумное поведение. Как мы увидим в главе 12, компьютеры сейчас общаются на уровне человека или даже выше по некоторым темам – хотя, конечно, к общему умственному развитию это никак не относится.

Рис. 3.10. CAPTCHA32
Имя Тьюринга упоминается в несколько вымученной аббревиатуре CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart), она же «капча», которая расшифровывается как «Полностью автоматизированный публичный тест Тьюринга, позволяющий отличать компьютеры от людей»[21]21
Альтернативное название на русском – «метод разделения попыток доступа со стороны машины и человека».
[Закрыть]. CAPTCHA представляет собой искаженные наборы букв вроде тех, что приведены на рис. 3.10. Она используется для попыток проверить, человек ли посетитель веб-сайта или программа. «Капча» – пример обратного теста Тьюринга, поскольку она пробует отличить человека от компьютера, полагаясь на тот факт, что люди, как правило, лучше машин распознают графические структуры. Конечно, CAPTCHA неприменима для тех, кто страдает нарушениями зрения.
Тьюринг – одна из самых важных фигур в информатике. Он внес основной вклад в наше понимание вычислений, и в его честь названа премия Тьюринга33 – эквивалент Нобелевской премии в области компьютерных наук. В последующих главах будет описано полдюжины важных изобретений в области информатики, авторы которых удостоились такой награды.
В 1952 году Тьюринга привлекли к ответственности за гомосексуальную активность, которая в то время в Англии преследовалась по закону. Он умер в 1954 году, по-видимому, покончив с собой34.