Суперскалярные и мультискалярные микропроцессоры
В современных микропроцессорах широко используется принцип конвейерного выполнения отдельных элементарных операций. Конвейеризация внутренних процессов позволяет выполнять команду за каждый процессорный цикл. Процесс выполнения команды можно разделить на следующие фазы (рисунок ):
1) ВК- выборка команды (Instruction Fetch): течение этой фазы по адресу команды она извлекается из ОЗУ (или кэша) в буфер команды, а программный счетчик увеличивается;
2) ДК- декодирование: на основании кода операции вырабатываются (устройством управления) сигналы, управляющие операционным блоком;
3) ВА- вычисление адреса операнда;
4) ВО-выборка операнда(ов): чтение операнда(ов) из регистров процессора или памяти;
5) ИК-исполнение команды в АЛУ;
6) ЗР-запись результата в регистр(ы).
В зависимости от команды отдельные фазы могут отсутствовать либо обойдены. Деление машинной операции на отдельные фазы осуществляется специальном блоке, называемом конвейером команд (Pipeline).
Такты® | ||||||||||||||
Команда 1 | ВК ↔ | ДК ↔ | ВА ↔ | ВО ↔ | ИК ↔ | ЗР ↔ | ||||||||
Команда 2 | ВК ↔ | ДК ↔ | ВА ↔ | ВО ↔ | ИК ↔ | ЗР ↔ | ||||||||
Команда 3 | ВК ↔ | ДК ↔ | ВА ↔ | ВО ↔ | ИК ↔ | ЗР ↔ | ||||||||
Команда 4 | ВК ↔ | ДК ↔ | ВА ↔ | ВО ↔ | ИК ↔ | ЗР ↔ | ||||||||
Команда 5 | ВК ↔ | ДК ↔ | ВА ↔ | ВО ↔ | ИК ↔ | ЗР ↔ | ||||||||
Команда 6 | ВК ↔ | ДК ↔ | ВА ↔ | ВО ↔ | ИК ↔ | ЗР ↔ | ||||||||
Команда 7 | ВК ↔ | ДК ↔ | ВА ↔ | ВО ↔ | ИК ↔ | ЗР ↔ | ||||||||
Команда 8 | ВК ↔ | ДК ↔ | ВА ↔ | ВО ↔ | ИК ↔ | ЗР ↔ | ||||||||
Команда 9 | ВК ↔ | ДК ↔ | ВА ↔ | ВО ↔ | ИК ↔ | ЗР ↔ |
Дальнейшее внедрение принципов конвейеризации привело к появлению класса суперскалярных микропроцессоров. Их отличительной особенностью является возможность выполнения нескольких команд параллельно, т.е. за один процессорный цикл. Такой режим выполнения программы стал возможным благодаря наличию в процессорах нескольких исполнительных устройств.
Есть два подхода к отображению внутреннего параллелизма обработки данных на архитектурном уровне в системе команд. Первый подход состоит в том, что никакого указания на параллельную обработку внутри процессора система команд не содержит. Такие процессоры относятся к классу суперскалярных.
Второй подход - открывает все возможности параллельной обработки. В специально отведенных полях команды каждому из параллельно работающих обрабатывающих устройств предписывается действие, которое устройство должно совершить. Такие процессоры называются процессорами с длинным командным словом (VLIW).
Типичный суперскалярный процессор выбирает команды и исследует их по мере выполнения. Исследование проводится с целью выявления и обработки команд перехода, идентификации типа команды для ее дальнейшего направления на соответствующий исполнительный блок или в буфер памяти. Выполняются также некоторые действия для смягчения зависимостей по данным, например переименование регистров. VLIW процессор возлагает на компилятор статическую реализацию тех функций, которые в суперскалярном процессоре выполняются динамически.
Основная идея, определяющая развитие суперскалярных микропроцессоров, состоит в построении возможно большего количества параллельных структур при сохранении традиционных последовательных программ. Это означает, что компиляторы и аппаратура микропроцессора сами, без вмешательства программиста, обеспечивают загрузку параллельно работающих функциональных устройств микропроцессора.
В соответствии с моделью последовательного программирования, программы пишутся в предположении, что команды будут выполнены в том же порядке, в каком они представлены в программе. Однако с целью достижения большей эффективности современные процессоры пытаются выполнять несколько команд одновременно и в некоторых случаях в порядке, отличном от их исходной последовательности в программе. Это переупорядочение может быть выполнено в трансляторе и (или) в аппаратных средствах во время выполнения. Суперскалярные и VLIW-процессоры принадлежат классу архитектур, которые используют параллельность уровня команды (ILP).
ILP-процессоры и компиляторы обычно преобразуют полностью упорядоченное множество команд исходной программы в частично упорядоченное множество, структурированное зависимостями по данным и управлению (командам). Зависимости по управлению (которые проявляются как переходы по условию) представляют главное препятствие высокопараллельному выполнению потому, что эти зависимости должны быть установлены прежде, чем будут выполнены все последующие команды.
Текст последовательной программы, представленной на языке высокого уровня, компилируется в машинный код, отражающий статическую структуру программы, т. е. упорядоченное множество команд (инструкций) в памяти компьютера. Процесс выполнения программы с конкретными наборами входных данных может быть представлен динамической структурой программы, т. е. множеством последовательностей инструкций в порядке их исполнения.
Повысить степень параллелизма программы можно путем изменения соответствующим образом ее статической или динамической структуры. Поскольку статическая структура программы однозначно соответствует ее исходному тексту (в предположении неизменности компилятора), то изменение статической структуры сводится к модификации исходного кода, что, в общем случае, не всегда возможно. Динамическая же структура программы может быть изменена при неизменной статической структуре. И главной целью такого изменения должно быть повышение степени параллельного исполнения команд.
Допустимые границы преобразования динамической структуры программы задают существующие на множестве инструкций отношения: зависимость по управлению и зависимость по данным. При описании архитектур суперскалярных процессоров часто используется модель окна исполнения. При исполнении программы микропроцессор как бы продвигает по статической структуре программы окно исполнения. Команды в окне могут исполняться параллельно, если между ними нет зависимости.
Для устранения зависимостей, вызванных командами переходов, используется метод предсказания, позволяющий извлекать и условно исполнять команды предсказанного перехода. Если позднее обнаруживается, что предсказание было сделано верно, то результаты условно исполненных команд принимаются. Если предсказание было ошибочным, состояние процессора восстанавливается на момент принятия решения о выполнении перехода.
Команды, помещенные в окно исполнения, могут быть зависимы по данным. Эти зависимости обусловлены использованием одних и тех же ресурсов памяти (регистров, ячеек памяти) в разных командах. Поэтому для правильного исполнения программы необходимо использование этих ресурсов в предписываемом программой порядке.
Все виды зависимостей по данным могут быть классифицированы по типу ассоциаций: RAR - "чтение после чтения", WAR - "запись после чтения" и WAW - "запись после записи", RAW - "чтение после записи". Некоторые из зависимостей по данным могут быть устранены. RAR, по сути дела, соответствует отсутствию зависимостей, поскольку в данном случае порядок выполнения команд не имеет значения. Действительной зависимостью является только "чтение после записи" (RAW), так как необходимо прочитать предварительно записанные новые данные, а не старые.
Лишние зависимости по данным появляются в результате "записи после чтения" (WAR) и "записи после записи" (WAW). Зависимость WAR состоит в том, что команда должна записать новое значение в ячейку памяти или регистр, из которых должно быть произведено чтение. Лишние зависимости появляются по нескольким причинам: не оптимизированный программный код, ограничение количества регистров, стремление к экономии памяти, наличие программных циклов. Важно отметить, что запись может быть произведена в любой свободный ресурс, а не только тот, который указан в программе.
После удаления лишних зависимостей по управлению и данным команды могут исполняться параллельно. Формирование расписания параллельного выполнения команд возлагается на аппаратные средства микропроцессора. Это расписание учитывает существующие зависимости между командами и имеющиеся функциональные модули процессора.
Типовая архитектура суперскалярного микропроцессора включает:
§ блок выборки команд и предсказания переходов;
§ блок декодирования команд и анализа зависимостей между ними;
§ блок переименования и диспетчеризации;
§ блоки регистров и обрабатывающих устройств с плавающей и фиксированной точками;
§ блок управления памятью;
§ блок упорядочения выполненных команд.
Ниже рассмотрены основные приемы повышения быстродействия в суперскалярных микропроцессорах.
Предварительная выборка команд и предсказание переходов. Поскольку при суперскалярной обработке необходимо извлекать из памяти несколько команд за один такт для загрузки параллельно работающих функциональных модулей, повышенные требования предъявляются к пропускной способности интерфейса микропроцессор-память. В современных микропроцессорах применяются многоуровневые раздельные кэш-памяти данных и команд.
Для уменьшения потерь процессорных циклов, связанных с промахами при обращении к кэш-памяти в случае выполнения команд ветвления, в состав системы кэширования введены средства предсказания переходов, основное назначение которых - повысить вероятность наличия в кэш-памяти требуемой команды.
Исполнение условных ветвлений состоит из следующих этапов:
§ распознание команды условного ветвления;
§ проверка выполнения условия перехода;
§ вычисление адреса перехода;
§ передача управления, в случае перехода.
На каждом этапе используются специальные приемы повышения производительности.
1. Для быстрого декодирования используются либо дополнительные биты в поле команды, либо преддекодирование команд при выборе из кэш - памяти команд.
2. Часто, когда команда уже выбрана в кэш, условие перехода еще не вычислено. Чтобы не задерживать поток команд в данном случае используется предсказание перехода по одной из нескольких возможных схем. Некоторые предсказатели используют статическую информацию из двоичного кода программы или специально выработанную компилятором. Например, определенные коды операций чаще вырабатывают ветвление, чем другие коды, или ветвление более вероятно (при организации циклов), или компилятор может устанавливать флаг, указывающий направления перехода. Может также использоваться статистическая информация, полученная при трассировке программы.
Другие предсказатели используют динамически формируемую информацию в процессе исполнения программы. Обычно это информация, касающаяся истории выполнения данного ветвления, сохраняемая в таблице ветвлений или в таблице предсказаний ветвлений. Таблица предсказания ветвлений организуется по ассоциативному принципу, подобно кэш-памяти, ее элементы доступны по адресу команды, ветвление которой предсказывается. В некоторых реализациях элемент таблицы предсказания ветвления является счетчиком, значение которого увеличивается при правильном предсказании и уменьшается при неправильном. При этом значение счетчика определяет преобладающее направление ветвлений.
В момент определения действительного значения условия ветвления, вносится изменение в историю ветвления. Если предсказание было неверным, то должна инициироваться выборка правильных команд. Результаты команд, которые были условно выполнены, должны быть аннулированы.
3. Для определения адреса ветвления обычно требуется выполнить целочисленное сложение, прибавляющее к текущему значению счетчика команд смещение, заданное в поле команды ветвления. И хотя это не требует дополнительных циклов для обращения к регистрам, ускорение вычисления адреса может быть достигнуто благодаря использованию буфера, содержащего ранее использованные адреса переходов.
Если требуется осуществить смену значения счетчика команд, то необходим, по крайней мере, один такт для распознания команды ветвления, модификации счетчика команд и выборки команды по заданному значению счетчика команд. Эти задержки вызывают пустые такты в конвейерах процессора. Более сложные решения используют буферы, содержащие наборы команд для двух возможных результатов ветвлений.
Возможно также использование "отложенных переходов", когда одна или несколько команд после команды ветвления выполняются безусловно.
Декодирование команд, переименование ресурсов и диспетчеризация. В этой фазе определяются существенные зависимости (RAW) по данным между командами и преодолеваются несущественные (WAW, WAR), производится распределение команд по буферам команд функциональных устройств.
При декодировании команды создается одна или несколько упорядоченных троек, каждая из которых включает: 1) исполняемую операцию, 2) указатели на операнды, 3) указатель на место помещения результата.
Для преодоления лишних WAR и WAW зависимостей, возникающих в результате ограниченности логических ресурсов (ячеек памяти, регистров), используется механизм динамического отображения определяемых текстом программы логических ресурсов на физические ресурсы микропроцессора. При данном подходе с одним логическим ресурсом может быть связано несколько значений в различных физических ресурсах, каждое из которых соответствует значению логической величины в один из моментов времени последовательного выполнения программы.
Когда команда создает новое значение для логического регистра, физический ресурс, в который помещается это значение, получает имя. Последующие команды, использующие это значение, снабжаются именем физического ресурса. Данная процедура называется переименованием регистров.
Для этого в микропроцессоре создается физический файл регистров размером больше логического. При необходимости переименования из списка свободных физических регистров берется один и ему сопоставляется соответствующее логическое имя. Если список свободных регистров пуст, диспетчеризация команд приостанавливается до момента появления свободных физических регистров.
Рассмотрим пример реализации данного способа переименования. Пусть требуется выполнить команду sub r3, г3, 5 (из значения регистра г3 вычесть константу 5 и поместить результат в регистр r3). Логические имена регистров начинаются со строчной буквы, а физические — с прописной. Пусть также в момент исполнения команды в таблице регистру r3 соответствует R 1. Первым регистром в списке свободных пусть является R2. Поэтому в поле результата команды sub r3, r3, 5 регистр r3 заменяется на R2. Исполнимая команда приобретает вид sub R2, R1, 5. Любая следующая за sub команда, использующая ее результат, должна использовать в качестве операнда R2.
Остается вопрос о возвращении физических регистров в список свободных после того, как из них считаны данные в последний раз. Один из способов связывает счетчик с каждым физическим регистром. Счетчик увеличивается при каждом переименовании операнда в командах, использующих этот физический регистр. Соответственно при использовании операнда значения счетчика уменьшается на 1. При достижении счетчиком нуля физический ресурс должен быть переведен в список свободных.
Исполнение команд.После формирования для каждой команды упорядоченных троек, состоящих из кода операции, физических операндов - источника и результата, и размещения их в буферах, наступает фаза динамической проверки готовности значений операндов для исполнения команды.
В идеале команда готова к исполнению, как только готовы ее входные операнды. Однако есть ряд ограничений, связанных с доступностью физических ресурсов, таких как исполнительные устройства, коммутаторы и порты регистровых файлов (или переупорядочивающего буфера). Для организации окна исполнения используются различные методы: одной очереди, многих очередей или метод резервирующей станции.
Если имеется одна очередь, то переименование регистров не требуется, так как доступность значений операндов может отмечаться битом резервирования, сопоставленным каждому регистру. Регистр резервируется, когда модифицирующая его команда назначается на исполнение. И регистр освобождается, когда заканчивается исполнение команды. Если для команды ресурсы не были зарезервированы, то она приостанавливает свое исполнение.
В методе многих очередей каждая очередь организуется для команд одного типа. Например, очередь команд с плавающей точкой или очередь команд работы с памятью.
Третий метод предполагает использование резервирующей станции, состоящей из совокупности элементов, каждый из которых содержит позиции для размещения кода операции, наименования первого операнда, самого первого операнда, признака доступности первого операнда, наименования второго операнда, самого второго операнда, признака доступности второго операнда и наименования регистра результата. Когда команда завершает исполнение и вырабатывает результат, то наименование результата сравнивается с наименованиями операндов в резервирующей станции.
Если в резервирующей станции обнаруживается команда, ждущая этого результата, то данные записываются в соответствующую позицию и устанавливается признак их доступности. Когда у команды доступны все операнды, инициируется ее исполнение. Резервирующая станция следит за доступностью операндов. Когда команда при диспетчеризации попадает в резервирующую станцию, все готовые операнды из регистрового файла переписываются в поля этой команды. Если все операнды готовы, команда исполняется. Иногда резервирующая станция содержит не сами операнды, а указатели на них в регистровом файле или переупорядочивающем буфере.
Завершение выполнения команды.Завершающей фазой исполнения команды является фаза изменения состояния процессора в соответствии с выполненной командой. Назначение этой фазы - сохранение последовательной модели исполнения программы, при реальном параллельном выполнении отдельных команд и условном выполнении команд ветвления.
Мультискалярные процессоры используют агрессивную стратегию выполнения кода с целью извлечения параллелизма уровня команд из последовательной программы, представленной на языке высокого уровня. В соответствии с данной стратегией программа разбивается на совокупность задач с помощью программных и аппаратных средств. Задача – это часть программы, выполнению которой соответствует непрерывная область динамической последовательности команд (например, часть базисного блока, базисный блок, множество базисных блоков, одиночная итерация цикла, полный цикл, обращение к функции, и т.д.).
На каждом шаге обхода программы мультискалярный процессор назначает одну задачу на один из процессорных элементов (ПЭ) для выполнения, без учета фактического содержания задачи, и продолжает обход. Задача назначается для выполнения некоторому процессорному элементу, передачей ему начального значения программного счетчика. Множество инициированных таким образом задач выполняется параллельно на процессорных элементах, результатом чего является выполнение множества команд за один процессорный такт.
Каждый из совместно используемых процессорных элементов выбирает и выполняет команды, принадлежащие выделенной ему задаче. Значения разделяемых процессорными элементами регистров копируются в каждый ПЭ. Результат модификации содержимого регистров динамически направляется множеству параллельных ПЭ в соответствии с генерируемыми компилятором масками.
Доступ к памяти осуществляется спекулятивно (условно, по предположению) без знания последовательности предшествующих команд загрузки или сохранения. Обращение к данным производится параллельно многими ПЭ, а обработка приостанавливается только в случае истинной зависимости данных.