ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 24.12.2021
Просмотров: 12183
Скачиваний: 10

Увеличение производительности 313
чтобы выполнение этих команд началось раньше, а полученные результаты были
бы доступны в тот момент, когда они понадобятся. Естественно, при каждой ите-
рации требуется только одно значение, поэтому остальные команды LOAD будут от-
брасываться, но если кэш-память и основная память конвейеризированы, то по-
добная процедура имеет смысл. Выполнение команды до того, как стало известно,
понадобится ли вообще эта команда, называется
спекулятивным выполнением.
Чтобы использовать эту технологию, требуется поддержка компилятора, аппарат-
ного обеспечения, а также некоторое усовершенствование архитектуры. В боль-
шинстве случаев переупорядочение команд за пределами одного базового элемен-
та находится вне компетенции аппаратного обеспечения, поэтому компилятор
должен перемещать команды явным образом.
В связи со спекулятивным выполнением команд возникают некоторые инте-
ресные проблемы. Например, очень важно, чтобы ни одна из спекулятивных ко-
манд не имела окончательного результата, который нельзя отменить, поскольку
позднее может оказаться, что эти команды не нужно было выполнять Обратимся
к листингу 4.6 и рис. 4 30. Очень удобно производить сложение, как только появ-
ляется значение
к
(даже до условною оператора if), но нежелательно сохранять
результаты в памяти. Чтобы предотвратить перезапись регистров до того, как ста-
ло известно, полезны ли полученные результаты, нужно переименовать (подме-
нить) все выходные регистры, которые используются спекулятивной командой.
Как вы можете себе представить, счетчик обращений для отслеживания всего это-
го очень сложен, но при наличии соответствующего аппаратного обеспечения его
вполне можно сделать.
Однако при наличии спекулятивных команд возникает еще одна проблема, ко-
торую нельзя решить путем подмены регистров А что происходит, если спекуля-
тивная команда вызывает исключение (exception)? В качестве примера можно
привести команду LOAD, которая вызывает промах кэш-памяти в компьютере с до-
статочно большим размером строки кэш-памяти (скажем, 256 байт) и памятью,
которая работает гораздо медленнее, чем центральный процессор и кэш. Если нам
требуется команда
LOAD
и работа машины останавливается на много циклов, на то
время, пока загружается строка кэш-памяти, то это не так страшно, поскольку
данное слово действительно нужно Но если машина простаивает, чтобы вызвать
слово, которое, как окажется позднее, совершенно ни к чему, это совершенно не
рационально. Если подобных «оптимизаций» слишком много, то центральный про-
цессор будет работать медленнее, чем если бы этих «оптимизаций» вообще не было.
(Если машина содержит виртуальную память, которая обсуждается в главе 6, то
спекулятивное выполнение команды LOAD может даже вызвать обращение к отсут-
ствующей странице Подобные ошибки могут сильно повлиять на производитель-
ность, поэтому важно их избегать )
В ряде современных компьютеров данная проблема решается следующим об-
разом. В них содержится специальная команда SPECULATIVE-LOAD, которая произво-
дит попытку вызвать слово из кэш-памяти, а если слова там нет, просто прекраща-
ет вызов. Если значение находится там и если в данный момент оно действительно
требуется, его можно использовать, но если оно в данный момент не требуется,
аппаратное обеспечение должно сразу получить это значение. А если окажется,
что данное значение нам не нужно, то никаких потерь не будет.

314 Глава 4. Микроархитектурный уровень
Более сложную ситуацию можно проиллюстрировать следующим выражением:
if (x>0)
z-y/x;
где х, у и z — переменные с плавающей точкой. Предположим, что все эти перемен-
ные поступают в регистры заранее и что команда деления с плавающей точкой
(эта команда выполняется медленно) перемещается вверх и выполняется еще
до условного оператора i f. К сожалению, если х равен 0, то программа завершается
в результате попытки деления на 0. Таким образом, спекулятивная команда при-
водит к сбою в изначально правильной программе. Еще хуже то, что программист
изменяет программу, чтобы предотвратить подобную ситуацию, но сбой все равно
происходит.
Одно из возможных решений — специальные версии команд, которые могут
вызвать исключения (exceptions). Кроме того, к каждому регистру добавляется
специальный бит
(poison bit).
Если спекулятивная команда дает сбой, она не вы-
зывает trap (ловушку), а устанавливает бит присутствия в регистр результатов.
Если этот регистр позднее используется обычной командой, происходит trap (как
и должно быть). Однако если этот результат не используется, бит присутствия сбра-
сывается и не причиняет программе никакого вреда.
Примеры микроархитектурного уровня
В этом разделе мы рассмотрим три современных процессора в свете понятий, изу-
ченных в этой главе. Наше изложение будет кратким, поскольку компьютеры чрез-
вычайно сложны, содержат миллионы вентилей и у нас нет возможности давать
подробное описание. Примеры будут те же, которые мы использовали до сих пор;
Pentium II, UltraSPARC II и picojava П.
Микроархитектура процессора Pentium II
Pentium II — один из процессоров семейства Intel. Он поддерживает 32-битные
операнды и арифметику, 64-битные операции с плавающей точкой, а также 8- и
16-битные операнды и операции, которые унаследованы от предыдущих процес-
соров данного семейства. Процессор может адресовать до 64 Гбайт памяти и счи-
тывать слова из памяти по 64 бита за раз. Обычная система Pentium II изображена
на рис. 3.47.
Как мы уже говорили раньше и как показано на рис. 3.40, картридж с одноряд-
ным расположением контактов (SEC) системы Pentium II состоит из двух интег-
ральных схем: центрального процессора (на котором находится разделенная кэш-
память первого уровня) и объединенной кэш-памяти второго уровня. На рис. 4.31
показаны основные компоненты центрального процессора: блок вызова/декоди-
рования, блок отправки/выполнения и блок возврата, которые вместе действу-
ют как конвейер высокого уровня. Эти три блока обмениваются данными через
пул команд — место для хранения информации о частично выполненных коман-
дах. Информация в пуле команд находится в таблице, которая называется
ROB
(ReOrder Buffer
—
буфер переупорядочивания команд).
Если излагать кратко,

Примеры микроархитектурного уровня
315
блок вызова/декодирования вызывает команды и разбивает их на микрооперации
для хранения в ROB. Блок отправки выполнения получает микрооперации из буфе-
ра ROB и выполняет их. Блок возврата завершает выполнение каждой операции
и обновляет регистры. Команды поступают в буфер ROB по порядку, могут выпол-
няться в произвольном порядке, но завершаться опять должны по порядку.
Связь с кэш-памятью
второго уровня
\7
Локальная шина,
связанная с мостом PCI
\7
Устройство сопряжения с шиной
Кэш-память первого
уровня для команд
Кэш-память первого
уровня для данных
1
Блок вызова
декодирования
Блок отправки
выполнения
•
Блок возврата
Задатчик
последовательности
микроопераций
Рис. 4 . 3 1 . Микроархитектура Pentium И
Блок сопряжения с шиной отвечает за обмен информацией с системой памяти
(и с кэш-памятью второго уровня, и с основной памятью). Кэш-память второго
уровня не связана с локальной шиной, поэтому блок сопряжения с шиной отвеча-
ет за вызов данных из основной памяти через локальную шину, а также за загрузку
всех блоков кэш-памяти. Система Pentium II использует протокол синхронизации
кэш-памяти MESI, который мы будем рассматривать, когда дойдем до мультипро-
цессоров в разделе «Архитектуры UMA SMP с шинной организацией» главы 8.
Блок вызова/декодирования
Блок вызова/декодирования отличается высокой степенью конвейеризации (со-
держит семь стадий). На рис. 4.32 эти семь стадий обозначены IFU0,..., ROB.
Блок отправки/выполнения и блок возврата имеют еще пять стадий, то есть всего
стадий 12. Команды поступают на конвейер на стадии IFUO (IFU — аббревиатура
от Instruction Fetch Unit — блок выборки команд), куда из кэша команд загружа-
ются целые 32-байтные строки. Всякий раз, когда внутренний буфер пуст, туда
копируется следующая строка кэш-памяти. Регистр NEXT IP (NEXT Instruction
Pointer — следующий указатель команды) управляет процессом вызова команд.

316
Глава 4. Микроархитектурный уровень
Кэш-память первого
уровня для команд
Стадия конвейера
IFU0
IFU1
IFU2
ID0
RAT
Блок выборки строк
кэш-памяти
Декодер длины команд
•
Блок выравнивания команд
•
m пи : ^
•
Блок формирования
очереди микрооперации
Распределитель регистров
Next IP
Устройство динамического
прогнозирования ветвления
Задатчик
поел едовател ьности
микроопераций
Устройство статического
прогнозирования ветвления
ROB
Микрооперации поступают
в регистр ROB
Рис. 4.32.
Внутренняя структура блока вызова/декодирования (в упрощенном виде)
Поскольку в наборе команд Intel, который часто называют IA-32 (32-разряд-
ная архитектура для процессоров Intel), содержатся команды разной длины и раз-
личного формата, на следующей стадии, IFU1, происходит анализ потока байтов,
чтобы определить начало каждой команды. В случае необходимости на стадии IFU1
может рассматриваться до 30 команд архитектуры IA-32 вперед. К сожалению,
вследствие этого обычно встречаются 4 или 5 условных переходов, не все из кото-
рых правильно прогнозируются, поэтому в обработке такого большого количества
команд заранее нет особого смысла. На стадии IFU2 команды выравниваются, по-
этому в следующей стадии они без труда декодируются.
Декодирование начинается на стадии Ш0 (Instruction Decoding — декодирова-
ние команды). Декодирование в системе Pentium II состоит из превращения каж-
дой команды IA-32 в одну или несколько микроопераций, как и в микроархитек-
туре Mic-4. Простые команды, например перемещение из одного регистра в другой,
переделываются в одну микрооперацию. Выполнение более сложных команд мо-
жет занимать до четырех микроопераций. Несколько чрезвычайно сложных ко-
манд требуют еще больше микроопераций и используют ПЗУ последовательнос-
ти микроопераций для упорядочения этих микроопераций.
На стадии ID0 имеется три внутренних декодера. Два из них предназначены
для простых команд, а третий обрабатывает остальные команды. На выходе полу-
чается последовательность микроопераций. Каждая микрооперация содержит код
операции, два входных и один выходной регистр.
Очередь микрокоманд выстраивается на стадии ID1. Этот блок аналогичен бло-
ку формирования очереди, изображенному на рис. 4.23. На этой стадии также про-

Примеры микроархитектурного уровня 317
исходит прогнозирование ветвления (сначала статическое, на всякий случай).
Прогноз зависит от нескольких факторов, но для переходов, связанных с текущей
командой, считается, что переходы назад будут производиться, а переходы впе-
ред — нет Затем идет динамическое прогнозирование с использованием специ-
ального алгоритма, как показано на рис. 4 29, только в данном случае для прогно-
зирования используется не два, а четыре бита. Должно быть ясно, что если речь
идет о конвейере с 12 стадиями, очень велика вероятность неправильного пред-
сказания, и поэтому нужно так много битов. Если перехода в таблице динамики
нет, используется статическое прогнозирование.
Чтобы избежать взаимозависимостей WAR и WAW, система Pentium II под-
держивает переименования (подмены), как мы видели в табл. 4.13. Реальные реги-
стры в командах IA-32 могут быть заменены в микрооперациях любым из 40 внут-
ренних временных регистров, находящихся в буфере ROB. Подмена происходит
на стадии RAT.
И наконец, микрооперации копируются в буфер ROB со скоростью три мик-
рооперации за цикл. Сюда же собираются операнды, если они имеются в наличии.
Если операнды микрооперации и регистр результатов доступны, а операционный
блок свободен, микрооперацию можно выпустить. В противном случае она нахо-
дится в буфере ROB, пока не появятся все необходимые ресурсы.
Блок отправки/выполнения
Перейдем к блоку отправки/выполнения, который изображен па рис. 4.33. Этот
блок устанавливает очередность и выполняет микрооперации, разрешает взаимо-
зависимости и конфликты ресурсов. Хотя за один цикл можно декодировать всего
три команды (на стадии ID0), за один цикл можно выпустить для выполнения це-
лых пять микроопераций, по одной на каждый порт. Такую скорость нельзя под-
держивать, поскольку она превышает способности работы блока возврата. Микро-
операции могут запускаться не по порядку, но блок возврата должен завершать их
выполнение по порядку. Чтобы следить за микрооперациями, регистрами и функ-
циональными блоками, требуется сложный счетчик обращений. Когда операция
готова для выполнения, она может начаться, даже если другие операции, которые
поступили в буфер ROB раньше нее, еще не готовы, Если несколько микроопера-
ций пригодны для выполнения одним и тем же функциональным блоком, с помо-
щью сложного алгоритма выбирается важнейшая из них, и именно она и запуска-
ется следующей Например, выполнение перехода гораздо важнее, чем выполнение
арифметического действия, поскольку первый из них влияет на ход программы.
Блок отправки/выполнения состоит из резервации и функциональных бло-
ков, которые связаны с пятью портами Резервация представляет собой очередь из
20 элементов для микроопераций, которые имеют собственные операнды. Они ожида-
ют своей очереди в резервации, пока не освободится нужный функциональный блок.
Между резервацией и функциональными блоками имеется пять портов. Неко-
торые функциональные блоки разделяют один порт, как показано на рисунке. Блок
загрузки и блоки запоминающих устройств выдают информацию для операций
загрузки и сохранения соответственно Для запоминающих устройств есть два пор-
та. Поскольку через один порт за один цикл может выдаваться только одна микро-
операция, то если двум микрооперациям нужно пройти через один и тот же порт,
одной из них придется подождать.