Проектирование процессорных ядер.
Часть 3. Микроархитектуры ядра

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

Вторая часть

Введение

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

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

 

Конвейеризация и блокировки

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

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

Задержки в конвейере данных для архитектуры «выборка – исполнение»

Рис. 1. Задержки в конвейере данных для архитектуры «выборка – исполнение»

Простейший конвейер, работающий по схеме «выборка – исполнение», имеет явно видимый потенциал развития. Рассмотрим рис. 1, где схематично показаны задержки в тракте данных. Здесь видно, что для подготовки операндов OpA и OpB для арифметико-логического устройства нужно сначала выбрать их из регистрового файла с помощью мультиплексора. Чем больше размер регистрового файла, тем более сложный мультиплексор для этого понадобится. Полученные операнды будут поданы на входы АЛУ, в котором также имеется мультиплексор, выбирающий результат из нескольких вариантов. Повышение тактовой частоты возможно, если применить конвейеризующие регистры, очевидным расположением для которых являются точки OpA и OpB на входе АЛУ.

Схема работы трехтактного конвейера «выборка – декодирование – исполнение»

Рис. 2. Схема работы трехтактного конвейера «выборка – декодирование – исполнение»

На рис. 2 показана архитектура, использующая трехтактный конвейер со стадиями «выборка» (Fetch), «декодирование» (Decode), «исполнение» (Execute). Такая схема потенциально достигает более высокой тактовой частоты, поскольку тракт данных конвейеризован и задержки чтения операндов из регистрового файла больше не прибавляются к задержке в АЛУ. На практике, тем не менее, необходимо оценить получаемый выигрыш, поскольку тактовая частота может быть ограничена и другими факторами.

Конвейер работает следующим образом:

  1. На стадии «выборка» по значению счетчика команд PC из памяти программ читается команда.
  2. На стадии «декодирование» прочитанная команда используется для выборки операндов и их записи во входные регистры АЛУ.
  3. На такте «исполнение» вычисленное значение записывается в регистровый файл.

При реализации такой схемы следует сразу обратить внимание, что прочитанная команда используется на двух различных стадиях. Поэтому следует создать конвейер и для команды, чтобы информация об операндах применялась на стадии «декодирование», а информация о выполняемой операции АЛУ — на стадии «исполнение», то есть была задержана на еще один такт.

Дальнейшим развитием данной архитектуры является 5‑ступенчатый конвейер, который также часто используется в процессорных ядрах. При рассмотрении 3‑ступенчатого конвейера можно убедиться, что с его помощью невозможно обеспечить чтение данных из синхронной памяти за один машинный цикл (при прохождении команды по всем трем стадиям). Действительно, при выполнении команды вида mov R0, [R1] будут выполнены следующие действия:

  1. Команда прочитана из памяти программ.
  2. Содержимое регистра R1 записано в выходной регистр и подано на вход адреса для памяти.
  3. Содержимое памяти по адресу, определяемому регистром R1, прочитано и находится на выходе блока памяти.

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

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

При интенсивной работе с памятью в конвейер могут быть добавлены такты, на которых и будут происходить чтение и запись в память. При 5‑ступенчатой архитектуре эти такты носят название Memory Phase и Writeback (рис. 3). На четвертом такте производится операция с памятью, а на пятом (Writeback) — запись результата по назначению.

Такты в процессоре с 5‐ступенчатым конвейером

Рис. 3. Такты в процессоре с 5‐ступенчатым конвейером

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

R1 = 1

R0 = 2

R1 = 3

R2 = R0 + R1

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

В приведенном листинге в регистры R0 и R1 загружаются операнды, которые затем складываются. Исходя из псевдокода результатом должно быть число 5. Однако временные диаграммы, показанные на рис. 4, демонстрируют явную ошибку: вместо сложения чисел 2 и 3 складываются 2 и 1. Из псевдокода видно, что 1 — это ранее загруженное в R1 значение и именно оно оказалось использовано для команды сложения.

Временные диаграммы исполнения псевдокода из листинга 1 с демонстрацией неверного поведения конвейеризованного процессора

Рис. 4. Временные диаграммы исполнения псевдокода из листинга 1 с демонстрацией неверного поведения конвейеризованного процессора

Такое поведение объясняется тем, что из-за конвейеризации процессору понадобится дополнительный такт, чтобы обновить значение в регистре. В момент выполнения команды R1 = 3 следующая команда находилась на стадии «декодирование», то есть читала операнды из регистрового файла. Поскольку новое значение для R1 находилось еще только на входе данных регистрового файла, по очередному фронту тактового сигнала произошло следующее:

  1. Старое значение R1 записано в регистр операнда.
  2. Новое значение записано в регистр R1.

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

  1. «Чтение после чтения» (RAR, Read After Read) — из одного и того же физического ресурса (регистра или ячейки памяти) производятся два последовательных чтения. Эта ситуация не формирует конфликтов, поскольку первое чтение не влияет на содержимое регистра и не мешает прочитать его второй раз.
  2. «Чтение после записи» (RAW, Read After Write) — наиболее проблемное положение, соответствующее показанному на рис. 4. При наличии конвейеризации может возникнуть ситуация, когда данные, предназначенные для записи, еще не попали в регистр (или память), однако следующая команда, находясь в конвейере, уже производит их чтение.
  3. «Запись после чтения» (Write After Read).
  4. «Запись после записи» (Write After Write).

Эти ситуации в принципе не вызывают проблем. Обращать внимание на них следует только в случае более сложного варианта микроархитектуры, который еще не был рассмотрен и соответствует случаю нескольких параллельно работающих конвейеров с внеочередным выполнением команд (обозначается термином out-of-order). По подобной схеме работает множество высокопроизводительных процессоров, где показательным примером является первый вариант процессора Intel Pentium, имевшего два конвейера (так называемые U‑ и V‑конвейеры). В более сложном конвейере команды могут быть запущены по мере готовности данных для них и выполняться путем прохождения разного количества стадий конвейера. Может возникнуть ситуация, когда команда, прочитанная из памяти позже, запустится на исполнение и будет реализована за меньшее количество тактов, чем предыдущая команда. Тогда необходимо проверить, не используют ли эти команды один и тот же ресурс процессора, так как порядок записи в регистр назначения может быть нарушен.

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

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

 

Архитектура процессора без блокировок в конвейере

Процессор без блокировок в конвейере (Microprocessor without Interlocked Pipeline Stages) — это и способ организации конвейера, и конкретный продукт, разработанный компанией MIPS Technologies (ранее MIPS Computer Systems). В данной архитектуре используется полезный прием разрешения конфликтов по доступу к регистрам, называемый «продвижение данных» (data bypass). Его суть можно проиллюстрировать на рис. 5.

Принцип продвижения данных в конвейере процессора MIPS

Рис. 5. Принцип продвижения данных в конвейере процессора MIPS

На рис. 5 можно видеть способ разрешения конфликта при последовательном доступе к одному и тому же регистру на запись и на чтение. Как было показано выше, такая ситуация должна вызвать конфликт, поскольку в момент записи нового значения на вход АЛУ попадает старое содержимое регистра. При реализации подхода data bypass новое значение записывается не только в сам регистр, но и в регистр операнда, если номер регистра для записи результата совпадает с номером регистра операнда.

Несмотря на то, что на рис. 5 показан дополнительный мультиплексор, при должном подходе снижение тактовой частоты такой схемы окажется несущественным. Для этого необходимо убедиться, что данные из АЛУ подаются именно на последний мультиплексор в цепочке, то есть после мультиплексирования одного из регистров в регистры OpA, OpB записывается либо значение регистра, либо данные из АЛУ. В этом случае суммарная задержка распространения сигнала от OpA, OpB через АЛУ увеличится всего на один мультиплексор «2‑в‑1».

 

Нестандартные микроархитектуры

В [2] рассматривается ряд процессорных микроархитектур, которые не нашли должного развития в силу допущенных концептуальных ошибок или же, как подчеркивается авторами, из-за несоответствия текущему технологическому уровню, потребностям рынка и тенденциям в технике. Такие архитектуры скорее могут рассматриваться как примеры не ошибок, а реализации ультимативных подходов к достижению каких-либо характеристик. С учетом эволюции элементной базы вполне может возникнуть ситуация, когда какие-то архитектурные решения окажутся полезными на новом витке технологической спирали. Интересно, что авторы [2] сравнивают неудачные архитектуры с динозаврами, отмечая при этом, что состоявшееся в истории вымирание динозавров не означает, что они были бы нежизнеспособны в сегодняшнем мире.

Пример 1.
Разработка высокоуровневого набора команд для поддержки специализированного языка или семейства языков программирования

Особенности подхода:

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

Исторически примерами подхода могут служить E‑mode-компьютеры B5000/6000/7000 компании Burroughs, разработанные начиная с 1960‑х годов для поддержки диалектов языка Algol, и их же системы B2000/3000/4000 с поддержкой языка Cobol. Последующий отход программной индустрии от этих языков показал, что обеспечить эффективное выполнение языка C затруднительно.

Пример 2.
Использование промежуточной архитектуры системы команд с целью эмуляции сложной машины на базе более простой

Подобный подход обладает как преимуществами, так и недостатками. Среди явных преимуществ можно отметить:

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

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

Пример 3.
Стековая машина

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

С точки зрения микроархитектуры стековая машина отличается минимальной (0‑адресной) командой, поскольку для стековой машины операнды заранее известны — они всегда находятся на вершине стека данных. Поэтому для стекового процессора можно заменить 3‑тактовый конвейер на 2‑тактовый, исключив стадию декодирования и выполняя чтение вершины стека заранее, параллельно с чтением кода следующей команды.

Стековая архитектура, как представитель 0‑операндной системы команд, для софт-процессора является достаточно привлекательной, так как позволяет получить проект, эффективно использующий дефицитную накристальную память ПЛИС. Например, вместо команды add r0, r1, r2 в стековом процессоре достаточно реализовать команду add, которая всегда работает с операндами, находящимися на вершине стека данных, и помещает результат вычислений на стек.

Пример 4.
Экстремальный CISC— и экстремальный RISC-подходы

Эволюция процессорных архитектур, начавшая с CISC-, или с процессоров со сложной («комплексной») системой команд, быстро выявила, что в практических программах часто применяется повторение простых команд, которые занимают значительную долю всех действий, выполняемых процессором. Поэтому архитектуры с сокращенным набором команд стали альтернативой, предлагающей уменьшение сложности процессора и повышение его тактовой частоты за счет сохранения, прежде всего, наиболее часто используемых команд. Однако первые варианты RISC-архитектур тратили больше тактов на выполнение тех же алгоритмов, что и CISC-процессоры, у которых отдельные команды позволяли закодировать больше действий, и выигрыш наблюдался за счет повышения тактовой частоты.

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

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

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

Пример 5.
Сверхдлинное командное слово (Very Long Instruction Word, VLIW)

Сверхдлинное командное слово требуется, если в команде процессора оказывается много отдельных полей. Потребность в дополнительных полях может возникнуть, если за один такт будет параллельно выполняться несколько операций. Пример организации конвейера данных VLIW-процессора показан на рис. 6. На рисунке видно, что несколько регистровых файлов (Reg1–Reg3) через коммутаторы подают операнды на несколько АЛУ (АЛУ1–АЛУ3). Коммутаторы могут иметь разные варианты организации (в примере показано, что выходы любого регистрового файла могут быть поданы на входы любого АЛУ), поэтому в таком процессоре возможно параллельное выполнение трех разных команд в трех АЛУ. Подобный подход соответствует параллелизму уровня инструкций (ILP, Instruction Level Parallelism).

Размер команды на рис. 6 увеличивается, потому что каждому из АЛУ необходимо определить выполняемую на этом такте операцию, а каждому коммутатору — выбираемый им операнд. Однако это не означает, что размер команды пропорционален количеству АЛУ. Если предположить, что команда имеет 32 разряда, добавление АЛУ потребует 4–5 разрядов для выбора операции, а дополнительному мультиплексору понадобится 2–3 разряда (в зависимости от количества его входов).

Пример архитектуры VLIW с несколькими регистровыми файлами и АЛУ

Рис. 6. Пример архитектуры VLIW с несколькими регистровыми файлами и АЛУ

Размер команды для VLIW-процессоров указывается в пределах 128–256 разрядов. Рекордсменом является процессор Avispa+ компании Silicon Hive, имеющий 768‑разрядную команду, однако при такой разрядности команды этот процессор имеет 60 слотов операций.

Преимущество VLIW заключается в возможности выполнения нескольких операций за один такт. Однако это формальное преимущество не всегда можно применить на практике. Для того чтобы параллельно выполнить несколько операций, для них должны быть готовы данные. Если типичные целевые алгоритмы предусматривают в основном линейные последовательности команд, в которых вычисленный результат используется как операнд следующей команды, дополнительные АЛУ, скорее всего, будут простаивать. Поэтому для VLIW большую роль играют предварительные исследования алгоритмов и возможности имеющегося компилятора.

Архитектура VLIW имеет разновидность, отмечающую тот факт, что в процессоре происходит прямое управление всеми вычислительными и коммутационными устройствами. Такая архитектура называется Explicit Parallel Instruction Computer (EPIC) — процессор с явным параллелизмом. Если для VLIW-процессоров часто использовались аппаратные планировщики, обеспечивавшие автоматический выбор операндов для АЛУ по мере их готовности, то в EPIC делается больший акцент на возможности компилятора по прямому управлению всеми устройствами процессора. Как и для VLIW, сам факт применения архитектуры EPIC не позволяет достичь увеличения производительности, если особенности выполняемой программы не предполагают параллельных вычислений.

Пример 6.
Чрезмерно агрессивная конвейеризация

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

Увеличение количества стадий конвейера наблюдалось в процессорах Intel Pentium. Если процессор P5 (Pentium первого поколения) имел пять стадий, то Pentium III использовал уже 10, а Pentium IV — 20 стадий (по некоторым данным, ядро Prescott имело 31‑ступенчатый конвейер). Следует отметить, что тактовые частоты Pentium IV при этом достигали 3–4 ГГц, что сопровождалось и ростом потребляемой мощности до 120 Вт. В конечном итоге подход, использованный в Pentium, был заменен в процессорах Intel Core Solo/Core Duo на более короткий конвейер, что снизило тактовую частоту, но итоговая производительность оказалась выше.

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

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

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

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

Рис. 7. Пример зависимости максимальной тактовой частоты от степени конвейеризации проекта.
Пример является абстрактным и не соответствует какой‐то определенной архитектуре

Пример 7.
Несбалансированная архитектура

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

1.  Процессор загружен или частично загружен.

     Это означает, что функциональные узлы процессора (регистры, АЛУ, интерфейсы памяти) имеют доступ к актуальным данным для обработки.

2.  Задержка латентности доступа.

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

3.  Задержка, вызванная недостаточной пропускной способностью интерфейсов.

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

Пример 8.
Программный обход блокировок конвейера

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

В приведенном примере абстрактного кода возникает блокировка по регистру R0:

R0 = R1 + R2                 (1)

R3 = R0 and R4               (2)

R5 = R6 or R7                (3)

При выполнении второй команды значение регистра R0 еще не будет обновлено, поэтому в R3 будет записана не сумма R1 и R2, а старое значение R0. Без аппаратного разрешения данной ситуации поведение процессора окажется непредсказуемым. При програм-мном же обходе компилятор может поступить следующим образом:

R0 = R1 + R2               (1)

R5 = R6 or R7              (3)

R3 = R0 and R4             (2) 

Если команду (3), которая не требует для работы обновляемого регистра R0, поставить перед командой (2), то во время ее выполнения R0 успеет обновиться и команда (2) получит в качестве операнда его новое значение. В простейшем случае после команды (1) можно поставить Nop (нет операции), что также даст дополнительный такт на обновление R0. Формально те же действия по вставке дополнительного холостого цикла выполняет процессор с аппаратным разрешением блокировок по данным (а процессоры с out-of-order выполнением команд реализуют аппаратную перестановку команд самостоятельно в ходе работы).

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

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

Пример 9.
Разрядность, не равная степени двойки, для процессоров общего назначения

Несмотря на то, что разрядность данных в процессорах обычно кратна 8, в цифровой схемотехнике существуют и другие величины разрядности, легко узнаваемые специалистами соответствующего профиля. Например, разрядность 24 бит характерна для обработки высококачественного звука, 18 бит является стандартной разрядностью входных операндов для блоков «умножение с накоплением» в FPGA. В настоящее время для обработки таких чисел можно использовать 32‑разрядные процессоры, размещающие в своих регистрах числа меньшей разрядности. При этом избыточность ресурсов будет, скорее всего, незаметна в масштабах всего проекта. Эффект от выбора разрядности, в точности подходящей для обрабатываемых данных, может проявиться в случаях массово‑параллельной системы, содержащей большое количество процессорных ядер. Тогда небольшая экономия от сокращения ресурсов одного ядра в конечном итоге выльется в значительный выигрыш в масштабах всего кристалла.

Исторически процессоры с разрядностью, не кратной 8, были характерны в основном для ранних этапов развития компьютерной техники. Так, 36‑битными были IBM 701/704x/709x, UNIVAC 1100 и 2200 и некоторые другие. Можно упомянуть и многоядерные процессоры SEAForth, разработанные автором языка Форт Ч. Муром. Эти процессоры применяют 18‑разрядные данные и выпущены в вариантах 24, 40 и 144 ядер (144‑ядерный процессор был анонсирован в 2011 году). В данном случае экстремальная минимизация размеров одного ядра позволила изготовить достаточно компактные полупроводниковые кристаллы.

Пример 10.
Слишком маленькое адресное пространство

Для процессора с небольшой разрядностью данных возникает вопрос, каким образом формировать адрес для работы с памятью. Если основные регистры процессора имеют разрядность 8 бит, они способны адресовать всего 256 ячеек памяти, чего для многих практических применений недостаточно. Также недостаточно может быть и 16 разрядов, которые обеспечивают адресацию 65 536 ячеек. По мере того как стоимость памяти уменьшалась, проблема формирования адреса становилась все более острой. Такие известные процессоры, как Intel 8080, Zilog Z80, Motorola 6800 и даже Intel 8086, имели ограничения на адресное пространство.

Подход, реализованный в процессоре Intel 8086, хорошо известен. Для адресации памяти в пределах 1 Мбайт используется комбинация сегментного адреса и смещения. Адрес вычисляется как (seg*16)+offset, где seg — содержимое сегментного регистра, а offset — смещение. Хотя и сегментный регистр, и смещение являются 16‑разрядными, в архитектуре i8086 они не образуют 32‑разрядный адрес, а максимальный размер адресуемой памяти составляет 1 Мбайт. Потребности программистов очень скоро показали, что этот размер недостаточен. Даже в рамках 20‑битного адреса стало возможным использовать High Memory Area (HMA), которая адресовалась путем задания максимального сегментного адреса 0xFFFF, формировавшего стартовый адрес 64‑кбит блока, всего на 16 байт отстоящий от конца памяти в 1 Мбайт. Добавление смещения в 16 и более формировало адрес, выходящий за пределы 20 разрядов, и это было востребовано для размещения драйверов, высвобождая основную память.

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

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

Пример 11.
Сегментированная адресация памяти

Сегментация памяти — один из вариантов решения проблемы слишком маленького адресного пространства, ограниченного разрядностью основных регистров процессора. Одним из способов является комбинация значений сегментного регистра, задающего начальный адрес, и смещения, как это было сделано в i8086. В то же время возможно комбинирование, например, двух 16‑разрядных регистров для получения 32‑разрядного адреса (или двух 8‑разрядных регистров для получения 16‑разрядного адреса). Такой подход, как упоминалось в предыдущем примере, позволяет использовать в программе только смещения, если обрабатываемый блок данных размещен целиком в одном сегменте памяти. Однако здесь же может образоваться ситуация, когда данные будут располагаться в разных сегментах памяти, что потребует постоянной перезагрузки и сегментного регистра, и регистра смещения.

Пример 12.
Многопоточность (multithreading)

В настоящее время многопоточная (multithreaded) архитектура представляет собой широко распространенную технологию для высокопроизводительных процессоров (Intel Core, IBM Power, AMD Opteron, Sun Niagara и др.). Поэтому ее упоминание в данном списке в основном отражает тот факт, что возможно построение процессоров и с чрезмерно большим количеством нитей (thread). Следовательно, данному вопросу нужно уделять особое внимание, поскольку их механическое увеличение приведет к неоднозначным результатам.

Идея многопоточности основана на том, что при повышении тактовой частоты процессорного ядра внешняя память не успевает реагировать на запросы доступа к ней с минимальной латентностью. Увеличение числа стадий конвейера также приводит к тому, что процессор в итоге тратит много тактов на продвижение данных по конвейеру и ожидание доступа к памяти. Чередование команд помогает не всегда, поскольку может иметь место линейный код с множественными зависимостями по данным, где просто не найдутся допустимые перестановки команд. После исчерпания возможностей ускорения одного потока вычислений можно запустить параллельный поток (thread — «нить»), если для него есть готовые данные. Многопоточное выполнение отличается от многозадачного (multitasking). Под многозадачностью понимается полное разграничение доступа к памяти между различными потоками выполнения (task — «задачи») таким образом, что одна задача ни при каких обстоятельствах не может изменить данные в памяти другой. Поэтому программные сбои в одной задаче не могут нарушить нормальную работу других задач в системе. В противоположность этому нити подразумевают параллельную работу нескольких потоков вычислений над общим пространством данных. Выигрыш предполагается в том, что при высвобождении ресурсов они могут быть использованы другой нитью, в результате удается достичь максимальной загрузки интерфейсов памяти, шин и прочих устройств процессора.

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

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

 

Заключение

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

В любом случае, принятие решения о выборе тех или иных черт микроархитектуры должно основываться не на ее «нестандартности», а на результатах всеобъемлющего моделирования, когда прототип процессора исследуется в составе системы, предполагающей запуск основных алгоритмов, которые будут использоваться при эксплуатации. Элементная база ПЛИС, позволяющая неограниченно перепрограммировать микросхему, — идеальная платформа не только для исследования процессорных архитектур, но и для их применения в небольших партиях изделий.

Продолжение.

Литература
  1. Корнеев В. В., Киселев А. В. Современные микропроцессоры. М.: Нолидж, 2000.
  2. Martin G., Leibson S. Beyond the Valley of the Lost Processors: Problems, Fallacies, and Pitfalls in Processor Design // Processor Design: System-on-Chip Computing for ASICs and FPGAs. 2007, June 28.
  3. www.plis.ru

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *