Проблемы реализации точного прерывания в конвейере

Обработка прерываний при конвейерной организации работы МП оказывается достаточно сложной из-за того, что совмещенное выполнение команд затрудняет определение возможности безопасного изменения состояния машины произвольной командой. В конвейерной системе команда выполняется по этапам. В ходе выполнения отдельных этапов команда может изменить состояние процессора. Тем временем возникшее прерывание может вынудить машину прервать обработку еще не завершенных команд.

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

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

При обсуждении этих конфликтов будем предполагать, что команда i предшествует команде j.


Рис. 9.2. Конфликт по данным типа RAW

Существует несколько типов конфликтов по данным:

1. Конфликты типа RAW (Read After Write - чтение после записи):

команда jпытается прочитать операнд прежде, чем команда iзапишет на это место свой результат. При этом команда jможет получить некорректное старое значение операнда.

Проиллюстрируем этот тип конфликта на примере выполнения команд, представленных на рис. 9.2.

Пусть выполняемые команды имеют следующий вид:

i) ADD R1,R0; R1=R1+R0i+1=j) SUB R2,R1; R2=R2-R1

Команда i изменит состояние регистра R1в такте 5. Но команда i+1 должна прочитать значение операнда R1 в такте 4. Если не приняты специальные меры, то из регистра R1будет прочитано значение, которое было в нем до выполнения команды i.

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

Уменьшение влияния конфликта типа RAW обеспечивается методом, который называется пересылкой или продвижением данных (data forwardINg), обходом (data bypassINg), иногда закороткой (short-circuitINg).

В этом случае результаты, полученные на выходах исполнительных устройств, помимо входов приемника результата передаются также на входы всех исполнительных устройств микропроцессора (рис. 9.3).


Рис. 9.3. Уменьшение влияния конфликта типа RAW методом продвижения данных

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

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

2. Конфликты типа WAR (Write After Read - запись после чтения):

команда j пытается записать результат в приемник, прежде чем он считается оттуда командой i. При этом команда i может получить некорректное новое значение операнда:

i) ADD R1,R0; R1=R1+R0i+1 = j) SUB R0,R2; R0=R0-R2

Этот конфликт возникнет в случае, если команда j вследствие неупорядоченного выполнения завершится раньше, чем команда i прочитает старое содержимое регистра R0.

3. Конфликты типа WAW (Write After Write - запись после записи):

команда j пытается записать результат в приемник, прежде чем в этот же приемник будет записан результат выполнения команды i, то есть запись заканчивается в неверном порядке, оставляя в приемнике результата значение, записанное командой i:

i) ADD R1,R0; R1=R1+R0. . .j) SUB R1,R2; R1=R1-R2

Устранение конфликтов по данным типов WAR и WAW достигается путем отказа от неупорядоченного исполнения команд, но чаще всего путем введения буфера восстановления последовательности команд.

Часть конфликтов по данным может быть снята специальной методикой планирования компилятора. В простейшем случае компилятор просто планирует распределение команд в базовом блоке. Базовый блок представляет собой линейный участок последовательности программного кода с одним входом и одним выходом, в котором отсутствуют внутренние команды перехода. Поскольку в таком блоке каждая команда будет выполняться, если выполняется первая из них, - можно построить граф зависимостей этих команд и упорядочить их так, чтобы минимизировать приостановки конвейера. Эта техника называется планированием загрузки конвейера (pIPelINe schedulINg) или планированием потока команд (INsTRuction schedulINg).

Например, для оператора А = B + С компилятор, скорее всего, сгенерирует следующую последовательность команд:

  1. Rb = B.
  2. >Rc = C.
  3. Ra = Rb + Rc.
  4. A = Ra.

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

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

Пусть, например, имеется последовательность операторов:

А = B + С;D = E - F.

В этом случае компилятор может сгенерировать следующую последовательность команд, выполнение которой не приведет к приостановке конвейера:

  1. Rb = B.
  2. Rc = C.
  3. Re = E.
  4. Ra = Rb + Rc.
  5. Rf = F.
  6. A = Ra.
  7. Rd = Re - Rf.
  8. D = Rd.

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

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

Зачастую зависимость по данным не является необходимой - просто так уж повелось у программистов: чем меньше переменных (и регистров в программах на ассемблере) использует программа - тем лучше. В результате зачастую получается, что вся программа использует один-два регистра с зависимостью по данным чуть ли не в каждой паре команд.

Устранение конфликтов, связанных с ложными взаимозависимостями данных, часто возможно путем переименования регистров (register renamINg). Суть этого механизма заключается в следующем. Процессоры, использующие переименование регистров, фактически имеют больше восьми регистров, определяемых архитектурой х86 или IA32. При этом если какой-либо команде требуется использовать регистр, процессор динамически ставит в соответствие этому логическому (архитектурному) регистру один из более многочисленных физических регистров. Если другая команда пытается обратиться к тому же логическому регистру, процессор для предотвращения конфликта может поставить ему в соответствие другой физический регистр. Такие переименования действуют, пока команды продвигаются по конвейерам.

Таким образом, каждый раз, когда команда прямо или косвенно пишет в регистр, ей выделяется новый физический регистр. В МП имеется таблица отображения логических (видимых программисту) регистров на физические (видимые только процессору). Когда команде выделяется новый физический регистр, таблица обновляется: логический регистр, на который ссылалась команда, ставится в соответствие выделенному физическому регистру (табл. 9.5).

 

Таблица 9.5. Механизм переименования регистров
Команда Действие Рабочий регистр
i Пишет в R0 С этого момента регистру R0 соответствует выделенный для команды регистр PHY0
i+1 Читает из R0 Читает из PHY0
i+2 Пишет в R0 С этого момента регистру R0 соответствует выделенный для команды регистр PHY1
i+3 Читает из R0 Читает из PHY1

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

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

Из табл. 9.5 видно, что команды стали независимы. Если команды, работающие с логическим регистром R0, зависят друг от друга и их нельзя выполнять параллельно, то микрокоманды "разведены" по физическим регистрам PHY0 и PHY1 и независимы.

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

Однако такой подход требует, чтобы микропроцессор помимо программно доступных архитектурных регистров содержал блок из гораздо большего количества невидимых программисту физических регистров, что и реализовано в большинстве современных микропроцессоров. Например, в микропроцессоре Itanium файл физических регистров имеет емкость 128 строк.

Как отмечалось выше, наличие конфликтов приводит к значительному снижению производительности микропроцессора. Определенные типы конфликтов требуют приостановки конвейера. При этом останавливается выполнение всех команд, находящихся на различных стадиях обработки (свыше 30 команд в Pentium 4). Другие конфликты, например, при неверном предсказанном направлении перехода, ведут к необходимости полной перезагрузки конвейера. Потери будут тем больше, чем более длинный конвейер используется в микропроцессоре. Такая ситуация явилась одной из причин сокращения числа ступеней в микропроцессорах последних моделей. Так, в микропроцессоре Itanium конвейер содержит всего 10 ступеней. При этом его тактовая частота составляет 1 МГц.

Краткие итоги. В лекции рассмотрена конвейерная организация работы микропроцессора. Дана оценка производительности идеального конвейера. Описаны конфликты в конвейере, снижающие производительность микропроцессора, и методы уменьшения негативного влияния этих конфликтов.



php"; ?>