M1 олицетворяет начало смены парадигмы, которая принесет пользу микропроцессорам RISC-V, но не так, как вы думаете.
Сейчас стало очевидным, что создание чипа Apple M1 — это примечательное событие. Постепенно становятся ясными последствия для всей отрасли. В этой статье я хочу поговорить о связи с микропроцессорами RISC-V.
Для начала небольшая предыстория: почему чип Apple M1 такой быстрый?
В той статье я говорил о двух факторах, влияющих на производительность M1. Одним из них было использование огромного количества декодеров и внеочередное исполнение (англ. out-of-order execution, OoOE).
Эта статья будет посвящена гетерогенным вычислениям. Apple придерживается стратегии добавления специализированных аппаратных модулей, которые в этой статье я буду называть сопроцессорами:
-
GPU (Graphical Processing Unit, Графический процессор) для графики и многих других задач с большим количеством параллелизма данных (выполнение одной и той же операции над многими элементами одновременно).
-
Neural Engine. Специализированное оборудование для машинного обучения.
-
Аппаратное обеспечение цифровой обработки сигналов для обработки изображений.
-
Аппаратное кодирование видео.
Вместо того, чтобы добавлять в свое решение больше процессоров общего назначения, Apple начала добавлять гораздо больше сопроцессоров, или “ускорителей”.
Это не совсем новая тенденция. Мой старый добрый ПК 1985 года выпуска Amiga 1000 имел сопроцессоры для ускорения звука и графики. Современные GPU по сути являются сопроцессорами. Тензорный процессор Google (Google Tensor Processing Unit, Google TPU) — это разновидность сопроцессоров, используемых для машинного обучения.
TPU Google — это интегральные схемы специального назначения (Application Specific Integrated Circuits, ASIC). Я буду называть их сопроцессорами.
Что такое сопроцессор?
В отличие от CPU, сопроцессор не может существовать один. Нельзя сделать компьютер, просто вставив в него сопроцессор. Сопроцессор — это как процессор специального назначения, который отлично выполняет конкретную задачу.
Одним из первых примеров сопроцессоров был Intel 8087 (FPU). Скромный микропроцессор Intel 8086 мог выполнять арифметические операции с целыми числами, но не с плавающей запятой. В чем разница?
Intel 8087. Один из первых сопроцессоров, используемых для вычислений, включающих числа с плавающей запятой.
Пример целых чисел (integers): 43, -5, 92, 4
. С ними довольно легко работать на компьютере.
Проблема начинается с десятичными дробями. Допустим, нужно сложить или умножить числа, например 4,25, 84,7
или 3,1415
. Это примеры чисел с плавающей запятой. Если бы количество цифр после точки было фиксированным, мы бы назвали это числами с фиксированной точкой. Обычно после точки ставится два десятичных знака.
Однако можно эмулировать арифметику с плавающей запятой с целыми числами, просто это будет медленнее. Это похоже на то, как ранние микропроцессоры тоже не умели умножать целые числа. Они могли только складывать и вычитать. Еще можно произвести умножение путем нескольких сложений. Например, 3 × 4
— это просто 4 + 4 + 4
.
Пример кода ниже поможет вам понять, как умножение может выполняться CPU только с помощью сложения, вычитания и ветвления (перехода в коде).
loadi r3, 0 ; Load 0 into register r3
multiply:
add r3, r1 ; r3 ← r3 + r1
dec r2 ; r2 ← r2 - 1
bgt r2, multiply ; goto multiply if r2 > 0
Если вы действительно хотите разбираться в микропроцессорах и коде на языке ассемблера, прочитайте мою статью, которая будет понятной для начинающих: Как работает современный микропроцессор?
Итак, можно добиться выполнения сложных математических операций путем повтора более простых.
Все сопроцессоры делают нечто похожее. CPU всегда может выполнить ту же задачу, что и сопроцессор. Однако обычно это требует повторения нескольких более простых операций. Для CPU повторение одних и тех же вычислений на миллионах пикселей является трудоемким.
Как данные передаются на сопроцессоры и от них
Давайте посмотрим на диаграмму ниже, чтобы лучше понять, как сопроцессор работает вместе с микропроцессором (CPU) или, другими словами, процессором общего назначения.
Обзор работы микропроцессора. Цифры перемещаются по цветным линиям. Ввод / вывод может быть осуществлен сопроцессорами, мышью, клавиатурой и другими устройствами.
Зеленые и голубые шины можно представить себе как трубки. Через эти трубки проталкиваются номера, чтобы достичь различных функциональных блоков CPU (показаны серыми полями). Входящие и исходящие данные (Input / Output) этих полей подключены к трубкам. Вы можете представить себе входящие и исходящие данные каждого блока как клапаны. Красные линии управления используются для открытия и закрытия этих клапанов. Таким образом, декодер, отвечающий за красные линии, может открывать клапаны на двух серых полях, чтобы числа перемещались между ними.
Можно представлять шины данных как трубы с клапанами, которые открывают и закрывают красные линии управления. Однако в электронике это делается с помощью так называемых мультиплексоров, а не настоящих клапанов.
Это позволяет нам объяснить, как данные извлекаются из памяти. Для выполнения операций с числами они нужны нам в регистрах. Декодер использует линии управления для открытия клапанов между серым полем памяти и полем регистров. Вот как это конкретно происходит:
-
Декодер открывает клапан на LSU (Load Store Unit), который заставляет адрес ячейки памяти течь по зеленой адресной шине.
-
Другой клапан открывается на модуле памяти, поэтому он может получить адрес. Он доставляется по зеленой трубе (адресная шина). Все остальные клапаны закрыты, поэтому, например, Input/Output не может получить адрес.
-
Выбирается ячейка памяти с заданным адресом. Его содержимое перетекает на синюю шину данных, потому что декодер открыл клапан для шины данных.
-
Данные в ячейке памяти могут течь куда угодно, но декодер только открыл входной клапан для регистров.
Такие вещи, как мышь, клавиатура, экран, GPU, FPU, Neural Engine и другие сопроцессоры, аналогичны окну ввода / вывода. Мы обращаемся к ним так же, как к ячейкам памяти. Жесткие диски, мышь, клавиатура, сетевые карты, графический процессор, DMA (прямой доступ к памяти) и сопроцессоры имеют сопоставленные адреса памяти.
Доступ к оборудованию осуществляется точно так же, как и к ячейкам памяти, путем указания адресов.
Что именно я имею в виду? Если процессор пытается читать из памяти по адресу 84, это может означать координату x вашей компьютерной мыши. А 85 означает координату y. Чтобы получить координаты мыши, вы должны сделать что-то вроде этого в ассемблерном коде:
load r1, 84 ; get x-coordinate
loar r2, 85 ; get y-coordinate
Для контроллера DMA могут быть адреса 110, 111 и 113, которые имеют особое значение. Вот созданная на коде ассемблера программа, использующая это для взаимодействия с контроллером DMA:
loadi r1, 1024 ; set register r to source address
loadi r2, 50 ; bytes to copy
loadi r3, 2048 ; destination address
store r1, 110 ; tell DMA controller start address
store r2, 111 ; tell DMA to copy 50 bytes
store r3, 113 ; tell DMA where to copy 50 bytes to
Так работает все. Вы читаете и пишете по специальным адресам памяти. Конечно, рядовые разработчики ПО этого никогда не увидят. Это делается с помощью драйверов устройств. Используемые программы видят только адреса виртуальной памяти там, где этого не видно. Но драйверы будут отображать эти адреса в адреса виртуальной памяти.
Я не буду много говорить о виртуальной памяти. Фактически мы получили реальные адреса. Адреса на зеленой шине будут переведены из виртуальных адресов в реальные физические. Когда я начинал программировать на C / C ++ в DOS, такого не было. Я мог просто установить указатель C, чтобы он указывал прямо на адрес видеопамяти, и начать писать прямо в него, чтобы изменить изображение.
char *video_buffer = 0xB8000; // set pointer to CGA video buffer
video_buffer[3] = 42; // change color of 4th pixel
Сопроцессоры работают таким же образом. Neural Engine, GPU, Secure Enclave и т. д. будут иметь адреса, с которыми вы взаимодействуете. Важно знать, что они могут работать асинхронно.
Это означает, что CPU может организовать целый набор инструкций для Neural Engine или GPU, которые он понимает, и записать их в буфер в памяти. Затем он сообщает сопроцессору Neural Engine или GPU о местонахождении этих инструкций, обращаясь к их адресам ввода-вывода.
Вы же не хотите, чтобы ЦП сидел и бездействовал, ожидая, пока сопроцессор проглотит все инструкции и данные. Вы также не хотите делать этого с прямым доступом к памяти. Поэтому обычно можно предусмотреть какое-то прерывание.
Как работает прерывание?
Различные карты, которые вставляются в компьютер, будь то видеокарты или сетевые карты, будут иметь определенную линию прерывания. Это что-то вроде линии, идущей прямо к CPU. Когда эта строка активируется, CPU отбрасывает все, что держит, чтобы справиться с прерыванием.
Или точнее, сохраняет в памяти свое текущее местоположение и значения своих регистров, поэтому он может вернуться к тому, что делал позже.
Затем он ищет в так называемой таблице прерываний, что делать. В таблице есть адрес программы, которую нужно запустить при срабатывании этого прерывания.
Как программист, вы этого не видите. Для вас это будет больше похоже на функции обратного вызова, которые вы регистрируете для определенных событий. Драйверы обычно справляются с этим на более низком уровне.
Зачем я рассказываю вам все эти занудные подробности? Потому что это помогает развить понимание происходящего при использовании сопроцессоров. В противном случае неясно, что на самом деле влечет за собой общение с сопроцессором.
Использование прерываний позволяет множеству вещей происходить параллельно. Приложение может получить изображение с сетевой карты, в то время как CPU прерывается компьютерной мышью. Мышь перемещена, и нам нужны новые координаты. CPU может их прочитать и отправить в GPU, чтобы он мог перерисовать курсор мыши в новом месте. Когда GPU рисует курсор мыши, CPU может начать обработку изображения, полученного из сети.
Точно так же с помощью этих прерываний можно отправлять сложные задачи машинного обучения в M1 Neural Engine, чтобы идентифицировать лицо на веб-камере. В то же время остальная часть компьютера реагирует, потому что Neural Engine перебирает данные изображения параллельно со всем остальным, что делает CPU.
Расцвет RISC-V
Еще в 2010 году в Калифорнийском университете в Беркли Лаборатория параллельных вычислений стала свидетелем развития более интенсивного использования сопроцессоров. Они увидели, что конец закона Мура означал, что больше не получится легко выжать больше производительности из ядер CPU общего назначения. Требуется специализированное оборудование — сопроцессоры.
Давайте на мгновение задумаемся, почему это так. Мы знаем, что тактовую частоту нелегко увеличить. Мы застряли на частоте около 3–5 ГГц. Поднимитесь выше, и потребление ватт и выделение теплоты будут зашкаливать.
Однако можно добавить намного больше транзисторов. Мы просто не можем заставить транзисторы работать быстрее. Таким образом, нам нужно выполнять больше работы параллельно. Чтобы это сделать, можно, например, добавить много ядер общего назначения. Можно добавить множество декодеров и выполнять внеочередное исполнение (Out-of-Order Execution, OoOE), как я уже говорил ранее: почему чип Apple M1 такой быстрый?
Бюджет транзисторов: ядра CPU или сопроцессоры?
Вы можете продолжать играть в эту игру, и в конечном итоге у вас будет 128 основных ядер, как у процессора Ampere Altra Max ARM. Но действительно ли это лучшее использование кремния? Для облачных серверов это оправдано. Вероятно, можно будет занять все эти 128 ядер различными клиентскими запросами. Однако настольная система может быть не в состоянии эффективно использовать более 8 ядер в обычных настольных рабочих нагрузках. Таким образом, если перейти, например, на 32 ядра, вы будете тратите кремний на множество ядер, которые большую часть времени будут бездействовать.
Возможно, вместо того, чтобы тратить весь этот кремний на большее количество ядер CPU, можно добавить больше сопроцессоров?
Давайте подумаем так: у вас есть транзисторный бюджет. Вначале, возможно, у вас был бюджет в 20 000 транзисторов, и вы полагали, что сможете сделать CPU на 15 000 транзисторов. Это близко к реальности начала 80-х. Теперь этот CPU может выполнять около 100 различных задач. Допустим, изготовление специализированного сопроцессора для одной из этих задач стоит вам 1000 транзисторов. Если сделать сопроцессор для каждой задачи, то получится 100 000 транзисторов. Это просто взорвет ваш бюджет.
Стратегия изменения количества транзисторов
Так, в ранних проектах нужно было сосредоточиться на неспециализированных вычислениях. Но сегодня мы можем наполнять микросхемы таким количеством транзисторов, что даже не знаем, что с ними делать.
Разработка сопроцессоров стала важным делом. Для создания новых сопроцессоров проводится много исследований. Однако они, как правило, содержат довольно тупые ускорители, с которыми приходится нянчиться. В отличие от CPU они не могут читать инструкции, в которых прописаны все шаги. Обычно они не знают, как получить доступ к памяти и что-либо организовать.
Обычным решением этой проблемы является использование простого CPU в качестве контроллера. Таким образом, весь сопроцессор — это некая специализированная схема ускорителя, управляемая простым CPU, который настраивает ускоритель для выполнения своей работы. Например, Neural Engine или TPU (Tensor Processing Unit), имеющие дело с очень большими регистрами, которые могут содержать матрицы (строки и столбцы чисел).
RISC-V был специально разработан для управления ускорителями
Именно для этого и был разработан RISC-V. Он имеет минимальный набор инструкций, состоящий из 40–50 инструкций, что позволяет ему выполнять все типичные функции процессора. Может показаться, что это много, но имейте в виду, что процессор x86 имеет более 1500 инструкций.
Вместо того, чтобы иметь большой фиксированный набор инструкций, RISC-V разработан на основе идеи расширений. Каждый сопроцессор будет отличаться от других. Таким образом, он будет содержать процессор RISC-V для управления, который реализует базовый набор инструкций, а также специальный набор инструкций расширения.
Возможно, вы теперь догадываетесь, к чему я клоню. Apple M1 действительно подтолкнет индустрию в целом к будущему, в котором будут доминировать сопроцессоры. И для создания этих сопроцессоров важной частью картины будет RISC-V.
Но почему? Разве каждый создатель сопроцессора не может просто изобрести свой собственный набор команд? В конце концов, я думаю, что Apple сделала именно это. Или, возможно, они используют ARM. Понятия не имею. Если кто-нибудь знает, пожалуйста, напишите мне.
В чем преимущество использования RISC-V для сопроцессоров?
Производство микросхем стало сложным и дорогостоящим делом. Создание инструментов для проверки микросхемы, запуск программ тестирования, диагностики и множества других вещей требует больших усилий.
Это часть ценности сегодняшнего использования ARM. У них есть обширная экосистема инструментов, которые помогут протестировать решение.
Таким образом, использование собственных проприетарных наборов инструкций — не лучшая идея. Однако с RISC-V есть стандарт, для которого несколько компаний могут создавать инструменты. Внезапно возникает экосистема, и компании могут разделить бремя.
Но почему бы просто не использовать уже имеющийся ARM? ARM сделан как CPU общего назначения, у него есть большой фиксированный набор инструкций. Под давлением клиентов и конкуренции с RISC-V ARM уступила и в 2019 году открыла набор инструкций для расширений.
Но проблема в том, что это не было сделано с самого начала. Вся цепочка инструментов ARM будет предполагать реализацию большого набора инструкций ARM. Это нормально для CPU Mac или iPhone.
Но для сопроцессора вам не нужен этот большой набор инструкций. Вам нужна экосистема инструментов, построенная на идее минимального фиксированного базового набора инструкций с расширениями.
Nvidia с использованием контроллеров на базе RISC-V
Почему это выгодно? Использование RISC-V компанией Nvidia дает некоторое представление. На их больших GPU им нужен какой-то CPU общего назначения, который будет использоваться в качестве контроллера. Однако количество кремния, которое они могут выделить для этого, и количество тепла, которое он может произвести, минимальны. Есть конкуренция за пространство.
Небольшой и простой набор команд RISC-V позволяет реализовать ядра RISC-V в гораздо меньшем количестве кремния, чем в ARM.
Поскольку RISC-V имеет такой небольшой и простой набор инструкций, он превосходит всех конкурентов, включая ARM. Nvidia обнаружила, что, выбрав RISC-V, они могут делать микросхемы меньшего размера, чем кто-либо другой. Они также снизили потребление ватт до минимума.
Таким образом, с помощью механизма расширения вы можете ограничиться добавлением только тех инструкций, которые имеют решающее значение. Контроллер для GPU, вероятно, нуждается в других расширениях, кроме контроллера на сопроцессоре шифрования, например.
RISC-V Machine Learning Accelerator (ET-SOC-1)
Esperanto Technologies — еще одна компания, которая нашла ценность в RISC-V. Они создают SoC под названием ET-SOC-1, который немного больше, чем SoC M1. В нем 23,8 миллиарда транзисторов по сравнению с 16 миллиардами на M1.
Вместо четырех ядер Firestorm общего назначения, это четыре ядра RISC-V под названием ET-Maxion. Они подходят для выполнения задач общего назначения, таких как запуск операционной системы Linux. Но в дополнение к этому он имеет более 1000 специализированных сопроцессоров под названием ET-Minion. Это сопроцессоры на основе RISC-V, которые реализуют векторное расширение RISC-V. Что это значит? Эти инструкции особенно хорошо подходят для обработки больших векторов и матриц, о которых и идет речь в современном машинном обучении.
Возможно, у вас возникли сомнения по поводу количества ядер. Как у ET-SOC-1 может быть столько ядер, чем у M1? Это связано с тем, что ядро Firestorm предназначено для работы с типичными рабочими нагрузками настольных компьютеров, которые нелегко распараллелить. Следовательно, необходимо использовать множество уловок, чтобы попытаться запустить код параллельно, что нетривиально для распараллеливания. Это съедает много кремния. Ядра ET-Minion, напротив, решают проблемы, которые легко распараллелить, и, таким образом, эти ядра могут быть действительно простыми, сокращая количество необходимого кремния.
Ключевым выводом ET-SOC-1 является то, что производители узкоспециализированных сопроцессоров видят ценность в создании сопроцессоров на основе RISC-V. Ядра ET-Maxion и ET-Minion будут лицензироваться Esperanto Technologies. Теоретически это означает, что Apple (или кто-либо другой) может лицензировать ядра ET-Minion и разместить множество их на своем M1, чтобы получить превосходную производительность машинного обучения.
ARM будет новой x86
По иронии судьбы, мы можем увидеть будущее, в котором ноутбуки и ПК будут работать на процессорах ARM. Но там, где их окружает все кастомное оборудование, RISC-V будет доминировать надо всеми их сопроцессорами. По мере того, как сопроцессор становится все более популярным, все больше кремния в системе на кристалле (System-on-a-Chip, SoC) может работать с RISC-V, чем с ARM.
Подробнее: RISC-V: Apple сделала неправильный выбор?
Когда я писал вышеупомянутую статью, я не совсем понимал, что такое RISC-V. Я думал, что будущее будет за ARM или RISC-V. Вместо этого, вероятно, это будут ARM и RISC-V.
ARM командует армией сопроцессоров RISC-V
В центре внимания будут процессоры ARM общего назначения с армией сопроцессоров на базе RISC-V, ускоряющих все возможные задачи: от графики, шифрования, кодирования видео, машинного обучения, обработки сигналов до обработки сетевых пакетов.
Профессор Дэвид Паттерсон и его команда из Калифорнийского университета в Беркли предвидели это будущее, и именно поэтому RISC-V так хорошо приспособлен для встречи с этим новым миром.
Мы наблюдаем такое массовое распространение и шум вокруг RISC-V во всевозможных специализированных аппаратных средствах и микроконтроллерах, что, я думаю, многие области, в которых сегодня доминирует ARM, перейдут на RISC-V.
Представьте себе что-то вроде Raspberry Pi. Теперь он работает под управлением ARM. Но будущие варианты RISC-V могут предложить множество вариантов, адаптированных под различные нужды. Могут быть микроконтроллеры машинного обучения. Другой может быть ориентирован на обработку изображений. Третий — для шифрования. По сути, вы можете выбрать свой собственный маленький микроконтроллер со своими особенностями. Вы можете запустить на нем Linux и выполнять все те же задачи, за исключением того, что профиль производительности будет другим.
Микроконтроллеры RISC-V со специальными инструкциями машинного обучения будут обучать нейронные сети быстрее, чем микроконтроллер RISC-V с инструкциями для кодирования видео.
Nvidia уже пошла по этому пути со своим Jetson Nano, показанным ниже. Это микроконтроллер размером с Raspberry Pi со специализированным оборудованием для машинного обучения, поэтому можно выполнять обнаружение объектов, распознавание речи и другие задачи машинного обучения.
Комплект разработчика NVIDIA Jetson Nano.
RISC-V в качестве главного CPU?
Многие спрашивают: почему бы не заменить полностью ARM на RISC-V? В то время как другие утверждают, что это никогда не сработает, потому что у RISC-V «маленький и простой» набор инструкций, который не может обеспечить такую высокую производительность, которую предлагают ARM и x86.
RISC-V можно использовать в качестве основного процессора. Производительность не мешает это делать. Как и в случае с ARM, нам просто нужен кто-то, кто сделает высокопроизводительную микросхему RISC-V. На самом деле, возможно, это уже было сделано: новый процессор RISC-V заявляет о рекордной производительности.
Распространено заблуждение, что сложные инструкции обеспечивают более высокую производительность. Рабочие станции RISC опровергли это еще в 90-х, когда уничтожили компьютеры x86 в тестах производительности.
Как Intel победила RISC-рабочие станции в 90-х: Is It Game Over для x86 ISA и Intel?
На самом деле у RISC-V есть много хитрых уловок для достижения высокой производительности: Гений микропроцессоров RISC-V.
В общем, нет причин, по которым основной CPU не мог быть процессором RISC-V, но это также вопрос динамики. MacOS и Windows уже работают на ARM. По крайней мере, в краткосрочной перспективе кажется сомнительным, что Microsoft или Apple потратят усилия на еще один переход.
Реклама которая может быть полезна
Прямо сейчас в OTUS действуют максимальные новогодние скидки на все курсы. Ознакомиться с полным списком курсов вы можете по ссылке ниже. Также у всех желающих есть уникальная возможность отправить адресату подарочный сертификат на обучение в OTUS.
Кстати, о «красивой упаковке» онлайн-сертификатов мы рассказываем в этой статье.