Добавил:
Rumpelstilzchen2018@yandex.ru Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

3-й семестр / Организация ЭВМиС; Орлов С.А., Цилькер Б.Я

..pdf
Скачиваний:
436
Добавлен:
25.12.2020
Размер:
5.43 Mб
Скачать

Суперскалярные процессоры

431

 

 

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

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

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

Процессор с поддержкой HTT эмулирует работу двух одинаковых логических процессоров, принимая команды, направленные для каждого из них. Это не означает, что в процессоре имеются два вычислительных ядра — оба логических процессора конкурируют за ресурсы единственного вычислительного ядра. Следствием конкуренции является более эффективная загрузка всех ресурсов процессора.

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

Сказанное проиллюстрируем на примере суперскалярного процессора с тремя функциональными блоками, каждый из которых способен выполнять только свой тип операций (рис. 9.35). На рис. 9.35, а показан обычный суперскалярный процессор, способный обрабатывать потоки команд лишь последовательно. В двухпроцессорном варианте (рис. 9.35, б) параллельная обработка нитей обеспечивается тем, что каждый из двух аналогичных процессоров обрабатывает свой поток независимо от другого. При таком подходе в каждом из процессоров в определенные моменты времени остаются незанятые функциональные блоки, которые, однако, не могут быть использованы для обработки команд из другой нити. В варианте с гиперпотоковой обработкой (рис. 9.35, в) единственный процессор параллельно обрабатывает два потока, загружая функциональные блоки, незадействованные одним потоком, подходящими командами из другого потока. Очевидно, что функциональные блоки гиперпотокового процессора используются с максимальной эффективностью.

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

432

Глава 9. Процессоры

 

 

Рис. 9.35. Пример обработки потоков команд: а — стандартная суперскалярная архитектура; б — двухпроцессорная суперскалярная архитектура;

в — гиперпотоковая архитектура

Следует учитывать, что эффективность HTT зависит от работы операционной системы, поскольку разделение команд на потоки осуществляет именно она.

Для иллюстрации рассмотрим некоторые особенности реализации гиперпотоковой технологии в процессоре Pentium 4 Xeon. Процессор способен параллельно обрабатывать два потока в двух логических процессорах. Чтобы выглядеть для операционной системы и пользователя как два логических процессора, физический процессор должен поддерживать информацию одновременно для двух отдельных и независимых потоков, распределяя между ними свои ресурсы. В зависимости от вида ресурса применяются три подхода: дублирование, разделение и совместное использование.

Дублированные ресурсы. Для поддержания двух полностью независимых потоков на каждом из логических процессоров некоторые ресурсы процессора необходимо дублировать. Прежде всего, это относится к счетчику команд, позволяющему каждому из логических процессоров отслеживать адрес очередной команды потока. Кроме того, каждому потоку выделяется свой набор регистров общего назначения (РОН) и регистров с плавающей запятой (РПЗ). С этой целью в процессоре имеются две таблицы распределения регистров (RAT, Register Allocation Table), каждая из которых обеспечивает отображение восьми регистров общего назначения (РОН) и восьми регистров с плавающей запятой (РПЗ), относящихся к одному логическому процессору, на совместно используемый регистровый файл из 128 РОН и 128 РПЗ. Таким образом, RAT — это дублированный ресурс, управляющий совместно используемым ресурсом (регистровым файлом).

Разделенные ресурсы. В качестве одного из видов разделенных ресурсов в Xeon выступают очереди (буферная память, организованная по принципу FIFO), расположенные между основными ступенями конвейера. Применяемое здесь разделение ресурсов можно условно назвать статическим: каждая буферная память (очередь)

Суперскалярные процессоры

433

 

 

разбивается пополам, и за каждым логическим процессором закрепляется своя половина очереди.

Применительно к другому виду очередей — очередям диспетчеризации команд (их в процессоре три) — можно говорить о динамическом разделении. Вместо фиксированного назначения двенадцати входов каждой очереди (например, входы 0–5 логическому процессору (ЛП) 0, а входы 6–11 — логическому процессору 1) каждому ЛП разрешается использовать любые входы очереди, лишь бы их общее число не превысило шести.

С позиций логического процессора и потока между статическим и динамическим разделением нет никакой разницы — в обоих случаях каждому ЛП выделяется своя половина ресурса. Различие становится существенным, если в качестве отправной точки взять физический процессор. Отсутствие привязки потоков к конкретным входам очереди позволяет не принимать во внимание, что имеются два потока, и расценивать обе половины как единую очередь. Очередь диспетчеризации команд просто просматривает каждую команду в общей очереди, оценивает зависимости между командами, проверяет доступность ресурсов, необходимых для выполнения команды, и планирует команду к исполнению. Таким образом, выдача команд на исполнение не зависит от того, какому потоку они принадлежат. Динамическое разделение очередей диспетчеризации команд предотвращает монополизацию очередей каким-либо одним из логических процессоров.

Отметим, что если процессор Xeon обрабатывает только один поток, то для обеспечения максимальной производительности этому потоку предоставляются все ресурсы процессора. В динамически разделяемых очередях снимаются ограничения на количество входов, доступных одному потоку, а в статических разделяемых очередях отменяется их разбиение на две половины.

Совместно используемые ресурсы. Этот вид ресурсов в гиперпотоковой технологии считается определяющим. Чем больше ресурсов могут совместно использовать логические процессоры, тем большую вычислительную мощность можно «снять» с единицы площади кристалла процессора. Первую группу общих ресурсов образуют функциональные (исполнительные) блоки: целочисленные операционные устройства, блоки операций с плавающей запятой и блоки обращения (чтения/записи) к памяти. Эти ресурсы «не знают», из какого ЛП поступила команда. То же самое можно сказать и о регистровом файле — второй разновидности совместно используемых ресурсов.

Сила гиперпотоковой технологии — общие ресурсы — одновременно является и ее слабостью.Проблемавозникает,когдаодинпотокмонополизируетключевойресурс (такой, например, как блок операций с плавающей запятой), чем блокирует другой поток, вызывая его остановку. Задача предотвращения таких ситуаций возлагается на компилятор и операционную систему, которые должны образовать потоки, состоящие из команд с максимально различающимися требованиями к совместно используемым ресурсам. Так, один поток может содержать команды, нуждающиеся, главным образом, в блоке для операций с плавающей запятой, а другой — состоять преимущественно из команд целочисленной арифметики и обращения к памяти.

434

Глава 9. Процессоры

 

 

Третьей разновидностью общих ресурсов является кэш-память. Процессор Xeon предполагает работу с кэш-памятью трех уровней (L1, L2 и L3) и так называемой кэш-памятью трассировки. Оба логических процессора совместно используют од­ ну и ту же кэш-память и хранящиеся в ней данные. Если поток, обрабатываемый логическим процессором 0, хочет прочитать некоторые данные, кэшированные логическим процессором 1, он может взять их из общего кэша. Из-за того, что в гиперпотоковом процессоре одну и ту же кэш-память используют сразу два логических процессора, вероятность конфликтов и, следовательно, вероятность снижения производительности возрастают.

Любой вид кэш-памяти одинаково трактует все обращения для чтения или записи, вне зависимости от того, какой из логических процессоров данное обращение производит. Это позволяет любому потоку монополизировать любую кэш-память, причем никакой защиты от монополизации процессор не имеет. Иными словами, физический процессор не в состоянии заставить логические процессоры сотрудничать при их обращении к кэш-памяти.

В целом, кэш-память — наиболее критичный из совместно используемых ресурсов, и конфликты за обладание ею сказываются на общей производительности процессора наиболее ощутимо.

По информации Intel, поддержка гиперпотоковой технологии в процессоре Pen­ tium 4 Xeon потребовала 5% дополнительной площади на кристалле, в то же время прирост скорости вычислений может достигать 25–35%. В приложениях, ориентированных на многозадачность, программы ускоряются на 15–20%. Возможны, однако, ситуации, когда прироста в быстродействии не будет или он станет отрицательным. Таким образом, эффективность технологии находится в прямой зависимости от характера исполняемого программного приложения. Максимальная отдача достигается при работе серверных приложений (за счет разнообразия процессорных операций). Отметим, что в случае отключении режима HTT (такая возможность предусмотрена во всех гиперпотоковых процессорах) производительность процессора при обработке одиночного потока не ухудшается.

Несмотря на некоторое охлаждение интереса к гиперпотоковой технологии, связанное с ее зависимостью от характера программных приложений, фирма Intel продолжает использовать HTT в своих многоядерных процессорах. Так, в процессорах класса Core 2 каждое ядро, по-прежнему, одновременно поддерживает два потока команд, но общее число параллельно обрабатываемых потоков возрастает пропорционально количеству ядер.

Программная поддержка технологии предусмотрена во всех версиях операционных систем Windows, начиная с Windows 2000.

Архитектура процессоров

Архитектура процессоров непосредственно вытекает их архитектуры заложенной в них системы команд. Ранее уже упоминались наиболее распространенные архитектуры системы команд: CISC, RISC, VLIW. К перечисленным архитектурам

Архитектура процессоров

435

 

 

следует добавить EPIC, являющейся разновидностью архитектуры VLIW. Основными отличительными характеристиками каждой отдельной архитектуры являются:

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

Обсудим их влияние на организацию процессоров.

Процессоры с архитектурой CISC

Основную идею CISC-архитектуры отражает ее название — «полный набор команд». В данной архитектуре стремятся иметь отдельную машинную команду для каждого возможного (типового) действия по обработке данных.

Исторически CISC-архитектура была одной из первых. Совершенствование процессоров шло по пути создания ВМ, способных выполнять как можно больше разных команд. Это упрощало работу программистов, которые писали программы на языке ассемблера (то есть практически на уровне машинных команд). Использование сложных команд позволяло сократить размер и время разработки программы.

В итоге сложились следующие черты организации CISC-процессоров:

большое количество различных машинных команд (сотни), каждая из которых выполняется за несколько тактов центрального процессора;

устройство управления с программируемой логикой;небольшое количество регистров общего назначения (РОН);различные форматы команд с разной длиной;преобладание двухадресной адресации;

развитый механизм адресации операндов, включающий различные методы косвенной адресации.

CISC-подход, однако, привел к тому, что некоторые команды стало невозможно выполнять чисто аппаратными средствами (при разумной сложности таких средств). В результате в процессорах появились блоки, «на лету» заменяющие наиболее сложные команды последовательностями из более простых команд. Мало того, практика показала, что многие сложные команды при написании программ оказывались просто невостребованны. Наконец, из-за высокой сложности команд и их обилия устройство управления ВМ приходилось строить только на основе программируемой логики, то есть с применением «медленной» управляющей памяти. Последнее обстоятельство существенно ограничивало возможности наращивания тактовой частоты процессора. Все эти факторы привели к повороту в сторону RISC-архитектуры. В то же время целый ряд несомненных достоинств CISCархитектуры сохраняют ее актуальность (прежде всего, в глазах разработчиков программных приложений). Именно поэтому ведущие фирмы-производители ВМ (Intel, AMD, IBM и др.) в своих последних разработках, по-прежнему, не отказываются от CISC-подхода.

436

Глава 9. Процессоры

 

 

Процессоры с архитектурой RISC

Особое внимание к RISC-архитектуре обусловлено тем, что в большинстве современных процессоров, относимых к классу CISC, сложные команды на стадии декодирования сводятся к набору простых RISC-команд, а ядро процессора реализуется как RISC-процессор.

Основные черты RISC-архитектуры

Главные усилия в архитектуре RISC направлены на построение максимально эффективного конвейера команд, то есть такого, где все команды извлекаются из памяти и поступают в ЦП на обработку в виде равномерного потока, причем ни одна команда не должна находиться в состоянии ожидания, а ЦП должен оставаться загруженным на протяжении всего времени. Кроме того, идеальным будет вариант, когда любой этап цикла команды выполняется в течение одного тактового периода.

Последнее условие относительно просто можно реализовать для этапа выборки. Необходимо лишь, чтобы все команды имели стандартную длину, равную ширине шины данных, соединяющей ЦП и память. Унификация времени исполнения для различных команд — значительно более сложная задача, поскольку наряду с регистровыми существуют также команды с обращением к памяти.

Помимо одинаковой длины команд важно иметь относительно простую подсистему декодирования и управления: сложное устройство управления (УУ) будет вносить дополнительные задержки в формирование сигналов управления. Очевидный путь существенного упрощения УУ — сокращение числа выполняемых команд, форматов команд и данных, а также способов адресации.

Очевидно, что в сокращенном списке команд должны оставаться лишь те, что используются наиболее часто. Исследования показали, что 80–90% времени выполнения типовых программ приходится на относительно малую часть команд (10– 20%). К наиболее часто востребованным действиям относятся пересылка данных, арифметические и логические операции.

Основная причина, препятствующая сведению всех этапов цикла команды к одному тактовому периоду — потенциальная необходимость доступа к памяти для выборки операндов и/или записи результатов. По этой причине желательно максимально сократить число команд, имеющих доступ к памяти, что добавляет к ранее упомянутым принципам RISC еще два:

доступ к памяти во время исполнения осуществляется только командами «Чте­ ние» и «Запись»;

все команды, кроме «Чтение» и «Запись», имеют формат «регистр-регистр».

Для упрощения выполнения большинства команд и приведения их к формату «регистр-регистр» требуется снабдить ЦП значительным числом регистров общего назначения. Это позволяет обеспечить временное хранение промежуточных результатов, используемых как операнды в последующих операциях, и ведет к уменьшению числа обращений к памяти, ускоряя выполнение операций. Минимальное число регистров, равное 32, принято как стандарт де-факто большинством производителей RISC-компьютеров.

Архитектура процессоров

437

 

 

Суммируя сказанное, концепцию RISC-процессора можно свести к следующим положениям:

выполнение всех (или, по крайней мере, 75% команд) за один цикл;

стандартная однословная длина всех команд, равная естественной длине слова и ширине шины данных и допускающая унифицированную конвейерную обработку всех команд;

малое число команд (не более 128);малое количество форматов команд (не более 4);

малое число способов адресации (не более 4);доступ к памяти только посредством команд «Чтение» и «Запись»;

все команды, за исключением «Чтения» и «Записи», используют внутрипроцессорные межрегистровые пересылки;

устройство управления с аппаратной логикой;

относительно большой (не менее 32) процессорный файл регистров общего назначения (согласно [152] число РОН в современных RISC-микропроцессорах может превышать 500).

Регистры в RISC-процессорах

Отличительная черта RISC-архитектуры — большое число регистров общего назначения, что объясняется стремлением свести все пересылки к типу «регистррегистр». Естественно, что увеличение числа РОН способно дать эффект лишь при разумном их использовании. Оптимизация использования регистров в RISCпроцессорах обеспечивается как программными, так и аппаратными средствами.

Программная оптимизация выполняется на этапе компиляции программы, написанной на языке высокого уровня (ЯВУ). Компилятор стремится распределить регистры процессора таким образом, чтобы разместить в них те переменные, которые в течение заданного периода времени будут использоваться наиболее интенсивно.

На начальном этапе компилятор выделяет каждой переменной виртуальный регистр. Число виртуальных регистров в принципе не ограничено. Затем компилятор отображает виртуальные регистры на ограниченное количество физических регистров. Виртуальные регистры, использование которых не перекрывается, отображаются на один и тот же физический регистр. Если в определенном фрагменте программы физических регистров не хватает, то их роль для оставшихся виртуальных регистров выполняют ячейки памяти. В ходе вычислений содержимое каждой такой ячейки с помощью команды «Чтение» временно засылается в регистр, после чего командой «Запись» вновь возвращается в ячейку памяти.

Задача оптимизации состоит в определении того, каким переменным в данной точке программы выгоднее всего выделить физические регистры. Наиболее распространенный метод, применяемый для этой цели, известен как раскраска графа. В общем случае метод формулируется следующим образом. Имеется граф, состоящий из узлов и ребер. Необходимо раскрасить узлы так, чтобы соседние узлы имели разный цвет и чтобы при этом общее количество привлеченных цветов было минимальным. В нашем случае роль узлов выполняют виртуальные регистры. Если два

438

Глава 9. Процессоры

 

 

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

На рис. 9.36 приведен пример раскраски графа [27], в котором шесть виртуальных регистров отображаются на три физических. Показаны временная последовательность активного вовлечения в выполнение каждого виртуального регистра (рис. 9.36, а) и раскрашенный граф (рис. 9.36, б).

Рис. 9.36. Иллюстрация метода раскраски графа: а — временная последовательность активного использования виртуальных регистров; б — граф взаимного использования регистров

Как видно, не удалось раскрасить только виртуальный регистр F, его придется отображать на ячейку памяти.

Аппаратная оптимизация использования регистров в RISC-процессорах ориентирована на сокращение затрат времени при работе с процедурами. Наибольшее время в программах, написанных на языках высокого уровня, расходуется на вызовы процедур и возврат из них. Связано это с созданием и обработкой большого числа локальных переменных и констант. Одним из механизмов для борьбы с этим эффектом являются так называемые регистровые окна. Главная их задача — упростить и ускорить передачу параметров от вызывающей процедуры к вызываемой и обратно.

Регистровый файл разбивается на группы регистров, называемые окнами. Отдельное окно назначается глобальным переменным. Глобальные регистры доступны всем процедурам, выполняемым в системе в любое время. С другой стороны, каждой процедуре выделяется отдельное окно в регистровом файле. Все окна имеют одинаковый размер (обычно по 32 регистра) и состоят из трех полей. Левое поле каждого регистрового окна одновременно является и правым полем предшествующего ему

Архитектура процессоров

439

 

 

окна (рис. 9.37). Среднее поле служит для хранения локальных переменных и констант процедуры.

База окна (начальный адрес, номер окна) указывается полем, называемым указателем текущего окна (CWP, Current Window Pointer), обычно расположенным в регистре (слове) состояния ЦП. Если текущей процедуре назначено регистровое окно j, CWP содержит значение j.

Рис. 9.37. Перекрытие регистровых окон

Рис. 9.38. Циклический буфер из пересекающихся регистровых окон

Каждой вновь вызванной процедуре выделяется регистровое окно, непосредственно следующее за окном вызвавшей ее процедуры. Последние k регистров окна j

440

Глава 9. Процессоры

 

 

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

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

На рис. 9.38 показан циклический буфер из шести окон, заполненный на глубину 4 (процедура А вызвала В, В вызвала С, С вызвала D). Указатель текущего окна (CWP) идентифицирует окно активной на данный момент процедуры — D, то есть окно О3. При выполнении процедуры все ссылки на регистры в командах преобразуются в смещение относительно CWP. Указатель сохраненного окна (SWP, Saved Window Pointer) содержит номер последнего из окон, сохраненных в памяти по причине переполнения циклического буфера. Если процедура D теперь вызовет процедуру E, аргументы для нее она поместит в общее для обеих поле регистровых окон (пересечение окон О3 и О4), а значение CWP увеличится на единицу, то есть CWP будет показывать на окно О4.

Если далее процедура Е вызовет процедуру F, то этот вызов при существующем состоянии буфера не может быть выполнен, поскольку окно для F (О5) перекрывается с окном процедуры А (О0). Следовательно, при попытке F начать загружать правое поле своего окна будут потеряны параметры процедуры А (А.вх). Поэтому когда CWP увеличивается на единицу (операция выполняется по модулю 6) и оказывается равным SWP, возникает прерывание, и окно процедуры А сохраняется в памяти (запоминаются только поля А.вх и А.лок). Далее значение CWP инкрементируется и производится вызов процедуры F. Аналогичное прерывание происходит и при возврате, например когда выполнится возврат из В в А. CWP уменьшается на единицу (по модулю 6) и совпадет со значением SWP. Обработка прерывания приведет к восстановлению содержимого окна процедуры А из памяти.

Как видно из примера, регистровый файл из n окон способен поддерживать n – 1 вызов процедуры. Число n не должно быть большим. В [150] показано, что при 8 регистровых окнах сохранение и восстановление окон в памяти требуется лишь для 1% операций вызова процедур. В ВМ Pyramid, например, используется 16 окон по 32 регистра в каждом.

Теоретически такой прием не исключен и в CISC. Однако устройство управления CISC-процессора оккупирует на кристалле более 50% площади, оставляя мало места для других подсистем, в частности для большого файла регистров. УУ RISCпроцессора занимает порядка 10% поверхности кристалла, предоставляя возможность иметь большой регистровый файл.

Другая часто встречаемая техника аппаратной оптимизации использования регистров — придание некоторым из них специального качества: такие регистры в состоянии принимать на себя имя любого РОН. Набор регистров, обладающих подобным свойством, называют буфером переименования. Прием оказывается очень