Конвейерная обработка микропроцессоров — аналогия с фабрикой роботов
Опубликовано: 24/01/2021 Время на прочтение: 10 минут
Заводской робот перемещает пакеты на воображаемом складе для обработки. Перемещение соответствует инструкциям ЦП, а пакеты можно рассматривать как обрабатываемые данные.
P ipelining во многом такой универсальный способ ускорить любые задачи, которые можно найти бесчисленное множество аналогий для него в производстве или в вашей повседневной жизни, например, стиркой, или приготовления пищи.
По сути, мы стремимся выполнить как можно больше работы за единицу времени. Есть много способов добиться этого. Я рассмотрю различные подходы, чтобы помочь вам понять, как разработчики микропроцессоров пришли к конвейерной обработке как к разумному решению. Мы будем смотреть на:
- Тактовая частота . Как ранние процессоры получали «лежачие полицейские» за счет увеличения тактовой частоты.
- Параллельное исполнение . Если вы не можете выполнить инструкцию быстрее, как насчет выполнения большего количества параллельно?
- Конвейерная обработка предназначена для случаев, когда вы не можете выполнять больше задач параллельно и не можете миниатюризировать, чтобы увеличить тактовую частоту.
Ускорение процессоров за счет увеличения тактовой частоты
Компьютер d о эс все в дискретных временных шагов, называемых тактовых циклов. За один такт ЦП выполняет самую маленькую задачу. Это немного похоже на то, как механические часы что-то делают, только когда шестеренки их шестерен движутся на один шаг. Между ними ничего не происходит.
Самый простой способ повысить производительность микропроцессора — сократить длину одного тактового цикла. Однако существует предел того, насколько коротким может быть тактовый цикл. Вы не можете заставить электроны двигаться быстрее. Они должны иметь возможность проходить через все необходимые транзисторы в вашем ЦП, чтобы завершить операцию, которую он должен выполнять за один такт.
Это легче пояснить с помощью аналогии со складским роботом. На складе у нас есть робот, который собирает посылки с одного конца и доставляет их с другого.
Можно сказать, что у этого робота тоже есть тактовый цикл. Цикл часов — это время, которое требуется роботу, чтобы доставить пакет в конце и вернуться в начало. Это означает, что задача перемещения пакета завершена. С точки зрения ЦП это время, необходимое для выполнения инструкции.
Складской робот перемещает оранжевую упаковку к концу очереди.
Как и в случае с электронами, мы должны представить, что ускорить робота невозможно. Если мы сделаем такт слишком коротким, робот не успеет доставить посылку и вернуться в отведенное время.
Представьте, что робот вернулся только на полпути, а затем вы даете ему указание забрать пакет и доставить его. За исключением того, что он не может забрать пакет, потому что он не находится в начальной точке.
Преимущества небольших процессоров
Если мы не можем заставить робота двигаться быстрее, как мы собираемся выполнить работу за меньшее время? С точки зрения ЦП вопрос заключается в следующем: если мы не можем заставить электроны лететь быстрее, как нам быстрее доставить их к месту назначения?
Простой ответ — уменьшить размер микропроцессора. В аналогии со складом это означает уменьшение расстояния, которое должен пройти робот. По сути, мы реорганизуем склад, чтобы сделать его более компактным. Мы уменьшаем его. Теперь робот может двигаться вперед и назад за более короткое время, что позволяет нам сократить каждый такт.
С меньшими расстояниями задача перемещения может выполняться быстрее.
Более короткие тактовые циклы равносильны более высокой тактовой частоте. Таким образом, миниатюризация электроники — это один из способов увеличить тактовую частоту и тем самым добиться большего.
Параллельное выполнение
Но есть предел тому, насколько мы можем миниатюризировать микропроцессор. Таким образом, следующим шагом разработчиков ЦП было параллельное выполнение дополнительных задач. Однако есть много способов добиться распараллеливания. Давайте посмотрим на пару стратегий.
Векторная обработка
Ранние суперкомпьютеры, такие как Cray-1, использовали векторные процессоры. В этом случае мы пытаемся сделать больше, обрабатывая данные параллельно. Это означало, что одна команда выполняла только одну инструкцию за раз, но одновременно выполнялась над несколькими элементами данных. По аналогии со складом робот должен забирать несколько пакетов за каждый проход.
Одновременное перемещение нескольких пакетов соответствует выполнению одной и той же операции над несколькими частями данных одновременно. Это то, что мы называем векторной обработкой.
Для более подробного изучения векторной обработки: векторные инструкции RISC-V против ARM и x86 SIMD.
Несколько ядер микропроцессора
Другой альтернативой было бы параллельное выполнение нескольких инструкций. Это то, что мы сегодня называем многоядерными процессорами. По аналогии со складом два или более робота работают параллельно.
В многоядерном процессоре несколько инструкций выполняются параллельно. В принципе, каждый складской робот может работать независимо от другого.
Конвейерная обработка
Наконец мы подошли к конвейерной обработке. Что делать, если вы не можете уменьшить размер микропроцессора? С точки зрения склада это означает, что вы не можете сократить расстояние до места назначения, куда необходимо доставить пакет (данные). Мы думаем о перемещении пакета как о выполнении инструкции.
Длина, которую мы перемещаем, связана с расстоянием, которое электроны должны пройти через транзисторы. В этом плане помогает миниатюризация. Но это также связано с тем, насколько сложна инструкция. Чем больше выполняется инструкция, тем через большее количество транзисторов должны пройти электроны.
Таким образом, мы можем думать о сложности инструкций как о чем-то, что удлиняет путь, по которому должны пройти электроны. Что, если мы не уменьшим размер самого процессора, а вместо этого уменьшим сложность каждой инструкции? Если мы упростим каждую инструкцию, то ток должен проходить через меньшее количество транзисторов. Один из способов сделать это — разделить инструкцию на несколько более мелких шагов.
Разделение перемещения пакета на 3 отдельных шага. Каждый робот несет пакет только на 1/3 пути.
Такт — 1
В нашей аналогии со складом это соответствовало бы добавлению большего количества роботов по одной и той же линии и позволяло бы каждому роботу перемещать пакет только частично. Обратите внимание, чем это отличается от распараллеливания, когда мы добавляем совершенно отдельные линии, по которым роботы могут перемещаться независимо друг от друга.
Два других складских робота сначала должны бездействовать, пока «трубопровод» заполняется. Первый робот перемещает оранжевый пакет на 1/3 пути. Это 1-й такт.
В этом случае происходит то, что первый робот не продвигается до конца. Скорее он перемещается на меньшее расстояние и падает с упаковки перед возвращением. Помните, что мы думаем о цикле часов как о времени, которое требуется каждому роботу, чтобы переместить пакет и вернуться за следующим пакетом. Это означает, что с помощью этой настройки мы можем сократить длину одного тактового цикла, что соответствует возможности увеличения тактовой частоты.
Первый тактовый цикл завершен. Второй робот не готов забрать оранжевый пакет и переместить его на 2/3 от конечного пункта назначения.
Такт — 2
В тактовом цикле номер два второй робот может начать перемещение оранжевого пакета, в то время как первый робот начинает поднимать и перемещать желтый пакет. Также обратите внимание, что парни со склада приносят новый пакет, зеленый.
Первый и второй складские роботы теперь могут перемещать пакеты параллельно. Но они должны делать это синхронно, чтобы избежать столкновения. Это второй такт.
Когда второй такт завершается, оранжевый пакет может быть поднят третьим роботом. Второй робот тем временем может забрать желтый пакет. И первый робот может забрать новую зеленую упаковку.
2-й такт завершен. Теперь весь «трубопровод» заполнен. В следующем тактовом цикле все три робота могут выполнять работу параллельно.
Такт — 3
В третьем такте все роботы движутся синхронно, продвигая свой пакет на следующий шаг. Стоит немного поразмыслить над тем, что здесь происходит. Время, необходимое для перемещения пакета от начала до самого конца, практически не изменилось. Представьте, что одному роботу потребовалось 30 секунд, чтобы переместить пакет полностью до конца. Теперь перемещение пакета на один шаг занимает 10 секунд, но нам нужно дерево шагов, поэтому общее время такое же.
Все три робота перемещают пакет синхронно. «Конвейер» заполнен, и именно тогда он работает наиболее эффективно, так как каждый такт мы доставляем пакет в конце и забираем новый.
Итак, что именно мы здесь получили? Преимущество в том, что каждые 10 секунд в конце доставляется новый пакет, потому что мы постоянно держим пакеты в полете. Мы оставляем новые пакеты в самом начале и ждем более короткое время, прежде чем их заберет робот.
Преимущества и проблемы конвейерной обработки
Мы можем описать это двумя важными концепциями информатики:
- Задержка — время, затрачиваемое на выполнение действия, до его завершения. Это может быть, например, время, необходимое для получения сетевого пакета после того, как вы его впервые запросили. В нашем случае мы можем рассматривать это как задержку завершения одной инструкции ЦП после начала выполнения.
- Пропускная способность — это то, сколько данных, инструкций или других вещей мы можем обрабатывать за каждую единицу времени. На складе это будет количество пакетов, доставленных в минуту, например, для нашего процессора это будет количество инструкций, которые мы выполняем в среднем за такт.
Пропускная способность улучшилась, потому что мы выталкиваем пакет каждые 10 секунд, тогда как раньше это занимало 30 секунд. Мы также могли увеличить пропускную способность за счет распараллеливания операций. Однако это не всегда возможно. Но именно так процессоры видеокарт получают свою огромную производительность. Они не так быстро выполняют каждую отдельную операцию. Другими словами, задержка не обязательно велика. Однако они выполняют огромное количество задач параллельно, что приводит к большой пропускной способности.
Но для ЦП общего назначения массовая парализация обычно невозможна. Таким образом, конвейерная обработка важна. Но, как мы видим на примере нашего склада, для того, чтобы это работало хорошо, каждый робот должен двигаться примерно одинаковой длины. В противном случае они не смогут двигаться синхронно. Таким образом, важно разбить инструкцию ЦП на несколько шагов равной длины.
RISC против микропроцессоров CISC
Это соображение является причиной того, почему ранние процессоры RISC, такие как процессор MIPS и SPARC, используемые на рабочих станциях Unix в 1990-х годах, были намного быстрее, чем их аналоги x86. Процессоры x86 — это процессоры CISC. Процессор CISC никогда не проектировался с учетом конвейерной обработки. Однако разработчик RISC имел это в виду. Инструкции RISC были специально разработаны для разделения на 4 логических шага. Таким образом можно было построить трубопровод глубиной в 4 ступени. Таким образом, для выполнения инструкции RISC потребуется 4 тактовых цикла, но за каждый тактовый цикл одна инструкция завершит выполнение.
Подробнее: Что означают RISC и CISC в 2020 году?
Intel поняла, что им нужно найти способ конвейеризации сложных инструкций переменной длины. Так они придумали микрооперации. Они разбивали сложные инструкции на несколько микроопераций, которые затем были достаточно простыми для передачи в конвейер.
Подробнее: Что, черт возьми, такое микрооперация?
Слишком далеко зайти в конвейер
Таким образом, Intel начала разделять свои инструкции на все меньшие и меньшие части, что позволило им резко увеличить тактовую частоту. Так, например, Pentium 4 был чудовищем по тактовой частоте. Это сделало конвейеры на процессорах Intel очень длинными.
И здесь мы натолкнулись на вещь, которую я еще не затронул: ветвление . Вы видите, что инструкции не приходят в виде одного бесконечного предсказуемого линейного потока. Реальные программы принимают решения и повторяют. Некоторые инструкции повторяются снова и снова. Разные типы данных должны обрабатываться разными инструкциями. Следовательно, в реальных программах есть условные переходы. Условие проверяется, а затем на основе этого условия ЦП выполняет переход в коде.
В чем проблема конвейерной обработки? Представьте, что у вас есть действительно глубокий конвейер со 100 инструкциями в полете. Вы можете представить себе это как 100 наших складских роботов, выстроившихся в очередь, перемещая 100 пакетов в один конец. Последняя завершенная инструкция — это инструкция условного перехода. В зависимости от результата этой инструкции ЦП может понять, что все те 100 инструкций, которые в настоящее время находятся в конвейере, на самом деле не являются правильными для выполнения. Предполагается, что мы собираем совершенно другие инструкции где-то еще в памяти.
Таким образом, весь конвейер должен быть очищен, и мы должны ждать целых 100 тактовых циклов, прежде чем другая инструкция пройдет по конвейеру до конца. Это большой успех.
Вот почему у Apple были слайды со сравнением чипов PowerPC на базе RISC, они использовали свои Mac до 2006 года с процессорами Intel Pentium. Процессор Pentium имел гораздо более высокую тактовую частоту, но и гораздо более длинный конвейер. Тогда люди считали тактовую частоту эквивалентом производительности. Как мы видели, это явно связано, но это не совсем то же самое.
Пентиумы часто промывали очень длинные конвейеры, что сильно снижало производительность. Между тем чипы PowerPC имели более низкую тактовую частоту, но гораздо более короткие конвейеры, что приводило к гораздо меньшему снижению производительности из-за условных переходов.
Ничего не стоит, что с тех пор мы уменьшили эту проблему, используя предикторы ветвления. Это означает угадывать, куда пойдет ветвь, до фактического выполнения инструкции, проверяющей условие.
Вероятно, это будет темой моей следующей технической статьи.