Подсистема памяти
Подсистема памяти осуществляет хранение данных и команд в быстродействующей кэш-памяти и взаимодействие процессора с оперативной памятью. К ней относятся следующие устройства.
Кэш данных первого уровня. Это память с малым временем доступа объемом 8 (для Pentium Pro) или 16 Кбайт (для более новых процессоров), предназначенная для хранения данных.
Кэш команд первого уровня. Эта память по своему быстродействию и объемам полностью аналогична кэш данных первого уровня, но используется для хранения команд.
Кэш второго уровня. В процессорах архитектуры Р6 впервые кэш-память второго уровня была реализована как отдельный кристалл, но интегрированный в корпус процессора и соединенный с кристаллом центрального процессорного устройства отдельной независимой шиной. Такая архитектура стала называться архитектурой с двойной независимой шиной. Напомним, что ранее кэш второго уровня реализовывался только на основе внешних микросхем памяти. Новая архитектура позволила обеспечить работу кэш-памяти с тактовой частотой процессора (или вдвое меньшей). При этом число транзисторов у этого кристалла даже больше, чем у самого процессора (для сравнения, кристалл ЦПУ базового процессора Р6 содержит 5,5 млн транзисторов, в то время как кристалл кэш-памяти второго уровня объемом 256 Кбайт – 15,5 млн).
Столь большое число транзисторов разъясняется статической природой памяти. Напомним, что у статической памяти для запоминания одного бита необходимо шесть транзисторов, в то время как у динамической памяти достаточно одного. Однако статическая память имеет более высокое быстродействие, нежели динамическая.
Кэш-память второго уровня в последующих процессорах архитектуры Р6 составляла 256, 512,1024 и 2048 Кбайт.
Блок шинного интерфейса. Это устройство обеспечивает управление системной шиной.
Порядок выполнения команд программы
Суперконвейерная архитектура, примененная в процессорах Р6, делит ступени стандартного конвейера на более мелкие части, чем в ранних процессорах Intel.
Это значит, что каждая отдельная ступень будет содержать меньше схемотехнических элементов, и время между подачей на их вход управляющих сигналов и получением результата станет меньше. Это, в свою очередь, позволяет повысить тактовую частоту работы процессора.
Конвейер состоит из 12 стадий:
1–4 – определение адреса команды и ее выборка;
5–6 – декодирование команды и преобразование в МО;
7 – переименование регистров;
8 – запись микроопераций в станцию-резервуар;
9 – передача МО из станции-резервуара к исполнительным блокам;
10 – исполнение МО (один или несколько тактов);
11 – 12 – завершение команды: запись результатов в регистры.
Блок выборки команды считывает поток команд из кэша команд первого уровня порциями по 32 байта за такт. Строки выбираются на основании информации из буфера предсказания переходов. В считанной строке с помощью вычислителя адреса следующей команды определяется начало команды. Если команда находится в конце строки, считывается вторая строка, откуда выбираются недостающие байты этой команды. Выровненные 16 байт команд передаются на три дешифратора.
ДШК состоит из трех параллельных дешифраторов, два из которых – простые (дешифраторы простых команд) и один – сложный (дешифратор сложных команд). Задача каждого дешифратора – преобразование команд х86 в одну или несколько МО.
Простые дешифраторы преобразуют команду в единственную МО. Сложный дешифратор работает с командами, которым соответствуют от одной до четырех МО. Некоторые особенно сложные команды передаются планировщику последовательности МО, который, обращаясь к таблицам, генерирует необходимую последовательность МО. Сначала все команды передаются дешифраторам простых команд. Если команда оказывается сложной, она передается дешифратору сложных команд либо планировщику последовательности МО. Такая пересылка слегка замедляет дешифрацию, но за счет буферизации с помощью станции-резервуара это незначительно сказывается на производительности процессора.
В принципе при бесперебойной и правильной загрузке командами дешифраторы способны генерировать в общей сложности шесть МО за такт, но, как правило, из всех трех дешифраторов за один такт выдаются три микрокоманды, соответствующие, в среднем, двум-трем командам х86, которые передаются в буфер переупорядочивания МО (пул команд).
Поскольку в классической архитектуре процессора х86 есть только восемь логических регистров общего назначения, то при параллельном выполнении нескольких команд весьма вероятна ситуация, когда одни и те же регистры будут использоваться в разных командах. Отсюда возникает необходимость использовать для разных команд разные физические регистры. Для этого предварительно нужно переназначить указанные в командах логические регистры на реальные регистры процессора, разные для разных команд. Ссылки в командах на логические регистры заменяются ссылками на реальные регистры, находящиеся в элементах буфера переупорядочивания МО (пула команд). Эта процедура выполняется в таблице назначения регистров.
Кроме того, здесь отслеживается порядок выполнения МО, соответствующих командам, таким образом, чтобы команды, использующие в качестве операндов результаты предыдущих команд, выполнялись позже. В случае необходимости записи результата в один и тот же регистр для двух разных команд они выстраиваются в очередь. Таким образом, более поздняя команда не может быть обработана до завершения более ранней команды.
Станция-резервуар выступает диспетчером и планировщиком МО, для чего она непрерывно сканирует буфер переупорядочивания МО (пул команд) и выбирает команды, готовые к исполнению, т.е. имеющие все исходные операнды. Результат выполнения возвращается назад в буфер и сохраняется вместе с МО до вывода. Поскольку результаты выполнения МО могут быть исходными операндами для следующих МО, они будут взяты непосредственно из пула команд. Порядок исполнения команд основывается не на их первоначальной последовательности, а на факте готовности команды и ее операндов к исполнению. Эта процедура называется out-of-order – исполнение с изменением последовательности. Такой порядок работы процессора был впервые реализован в советском сунеркомньютере "Эльбрус", а его ведущий разработчик В. М. Пентковский, ставший после развала Советского Союза руководителем проекта Pentium Pro, использовал эту идеологию при создании микроархитектуры Р6. Исполнение команд программы с изменением последовательности их выполнения стало одним из краеугольных камней микроархитектуры Р6, обеспечившим резкий подъем производительности процессора.
Всего станция-резервуар может одновременно выдать на исполнительные блоки, работающие параллельно, пять МО. Однако такая ситуация возникает довольно редко. Гораздо чаще на них выдается три МО за такт.
Рассмотрим, как будет работать процессор Р6 при выполнении следующего фрагмента программы (номера регистров – условные):
(r1) ← (тет [r0]) (тет [r0] – ячейка памяти по адресу из r0)
(r2) ← (r2) + ΟΙ)
(r5) ← (r5) + 1
(r6) ← (r6) – (r3).
При выполнении первой МО сначала будет обращение к кэш-памяти. Если фрагмент памяти с нужной ячейкой в кэше присутствует, он будет считан, и процессор продолжит выполнение программы. Если же данных в кэше нет, при традиционном подходе (в том числе и в процессорах Pentium) будет выполнено обращение к памяти, и пока данные через интерфейс не будут считаны, процессор будет простаивать. И это при том, что за это время он мог бы выполнить 20–30 МО, не требующих обращения к памяти.
Идеология процессора Р6 заключается в том, чтобы сводить к минимуму возможные простои и выполнять максимально возможный в каждой конкретной ситуации объем полезной работы.
В рассматриваемом случае станция-резервуар обратится к пулу команд и выберет оттуда МО, для которых все операнды уже имеются в наличии. Так как выполнить вторую
МО до завершения первой нельзя, будут выбраны третья и четвертая, для которых все операнды уже готовы. Они будут отправлены на исполнительные блоки. После выполнения МО вместе с результатом будут возвращены в пул команд в свой 256-битный элемент, при этом бит состояния МО будет установлен в состояние "Микрооперация выполнена".
Выполненная МО будет находиться в пуле команд до тех пор, пока все впереди стоящие МО не будут исполнены, т.е. фрагмент программы не будет выполнен полностью. Лишь после этого МО можно удалить из пула команд, а результаты всего фрагмента программы записать в истинные регистры процессора (или в ячейки кэш-памяти – в зависимости от указаний исходной программы). Такой порядок выполнения команд программы называется опережающим.
Таким образом, процессор Р6 исполняет команды программы, преобразованные во внутренние МО, только исходя из их готовности к выполнению, независимо от исходной последовательности команд в программе.
Чтобы закончить фрагмент программы, нужно из исполненных МО выбрать те, которые уже не будут влиять на ход программы, извлечь их из пула команд и записать результаты работы программы в соответствии с исходной последовательностью команд. Эту работу выполняет буфер завершения.
Процесс завершения занимает два такта. Буфер завершения сканирует пул команд и отыскивает МО, не влияющие на исполнение оставшихся в пуле команд. Затем он выстраивает их в первоначальную последовательность и выводит МО. При выводе результат МО записывается в регистровый файл, содержащий восемь регистров общего назначения и восемь регистров для данных с плавающей точкой. Именно они соответствуют логическим регистрам процессора архитектуры х86. Только после этого МО удаляется из пула команд. Всего буфер завершения может выводить три МО за такт.
Мы рассмотрели работу процессора при линейном порядке следования команд, однако в программах, в среднем, 10–20% составляют команды условного перехода. В этом случае для устранения непроизводительных потерь времени, связанных с обращением к основной памяти, необходимо выполнять команды, следующие после команд условных переходов. Заранее неизвестно, по какой из ветвей должен пойти вычислительный процесс, поэтому необходимо определить наиболее вероятный путь продолжения программы, выполнить вычисления, сохраняя их результаты в пуле команд, а после того как будет окончательно определено, правильно был угадан ход выполнения программы или нет, записать полученные результаты или аннулировать их.
Как уже отмечалось, за время обращения к памяти процессор может выполнить до 20–30 микроопераций, среди которых до пяти могут оказаться условными переходами. Определением возможных адресов переходов занимается буфер предсказания переходов. Для предсказания переходов используется расширенный алгоритм Yeh'a, позволяющий с вероятностью 90% правильно определить, будет ли выполнен возврат в начало цикла программы (команды которой уже имеются в кэше) или нет. В буфере хранятся адреса переходов, выполненных ранее. Очевидно, что если на ранних стадиях выполнения циклической программы переход был выполнен по одному и тому же адресу, то, скорее всего, очередной переход будет выполнен туда же.
Если предсказание окажется верным, то исполнение продолжится. Если же предположение ошибочно (цикл программы закончился), то частично выполненные МО удаляются из пула команд, команда с правильным адресом и следующие за ней выбираются, декодируются и отправляются на исполнение. Это приводит к существенному снижению производительности, напрямую зависящему от глубины конвейера – для архитектуры Р6 в случае ошибочного предсказания перехода потери составят 4–15 тактов.
Проверка правильности ранее предсказанных переходов осуществляется следующим образом. При дешифрации к команде условного перехода прикрепляются оба адреса. Один из них – предсказанный – предполагается правильным, другой – нет. Как уже отмечалось, один из исполнительных блоков ALU специально предназначен для выполнения операций условного перехода. Он определяет правильный адрес перехода и сравнивает его с предсказанным. Если адреса совпадают, то все МО этой ветви программы, находящиеся в нуле команд, отмечаются как годные, и исполнение ветви продолжается. Если же адреса не совпадают, т.е. адрес перехода был предсказан неправильно, то блок ALU изменяет статус всех команд ветви на "Подлежащие удалению". При этом он передает правильный адрес в буфер предсказания переходов, а тот, в свою очередь, – вычислителю адреса следующей команды. Работа конвейера процессора начинается с нового адреса команды.
Операции записи в память, в отличие от операций с логическими регистрами, выполненные один раз, уже не могут быть отменены. Поэтому они откладываются до той поры, пока вызвавшая их МО не будет удалена из пула команд. Для этого в Р6 предусмотрен буфер переупорядочивания памяти. В нем по командам, выдаваемым блоком интерфейса памяти MIU, сохраняется информация о данных и адресах. Буфер пересылает данные в память только после того, как МО, произведшая запись в память, удаляется.
Таким образом, процессор Р6 за счет рационального порядка исполнения команд программы обеспечивает существенное повышение производительности, при этом, несмотря на изменение порядка выполнения команд программы, результаты работы формирует в точном соответствии с программой.