Трубопровод и опасности | Кодементор
Конвейерная обработка — это подход, позволяющий сократить время цикла. Мы рассмотрим классический 5-этапный конвейер в стиле MIPS и RISC V.
Конвейерная обработка работает путем разделения работы для одной инструкции на несколько более мелких частей, каждая из которых может выполняться быстрее из-за меньшего количества работы по сравнению с выполнением всей работы для одной инструкции в одном цикле. Итак, это означает, что мы можем запускать часы быстрее за счет того, что инструкция занимает несколько циклов.
Части инструкции разбиваются на этапы, которые выполняются последовательно для одной инструкции, так что конвейеру с 5 глубинами потребуется 5 циклов для выполнения инструкции. Однако выполнение одной инструкции — и следующей, и следующей — перекрыватьтак что (в идеале) одна инструкция входит в конвейер каждый цикл, а также выходит.
Из-за этого перекрытия одна инструкция завершает (в идеале) каждый цикл, и, таким образом, циклы процессора на инструкцию, CPI ближе к 1, чем к 5, которые мы могли бы ожидать. Выполнение одной инструкции распределено по 5 циклам, но выполнение примерно 5 инструкций одновременно перекрывается.
Однако, поскольку выполнение одной инструкции растянуто во времени, это вводит понятие опасности, когда значение конечного результата предыдущей инструкции еще не готово для использования в начале последующей инструкции. Поскольку все инструкции растянуты во времени, их перекрытие может вызвать проблемы при наличии зависимостей.
Прежде чем мы перейдем к конкретному примеру диаграммы конвейера, давайте обсудим различные подходы к построению диаграмм или иллюстрации конвейеров. У нас есть 3 основных компонента, которые мы пытаемся показать:
- время — которое увеличивается,
- инструкции — которые также увеличивают, и,
- этапы конвейера — которые фиксированы.
Один из популярных подходов к диаграмме конвейера, показывающий взаимосвязь между этими тремя понятиями, заключается в следующем:
Основная сила этого подхода заключается в том, что он следует привычному подходу горизонтальной временной шкалы, где время увеличивается по мере движения слева направо.
Однако у этого подхода есть существенный недостаток, заключающийся в том, что и ось x, и ось y расширяются, как показано стрелками на обеих осях. Если мы доведем это даже до 50 инструкций, диаграмма выйдет за пределы столбца 50 и строки 50!! Этот подход не масштабируется до сотен (не говоря уже о тысячах) инструкций.
При выполнении исследовательского проекта мы можем зафиксировать следы от тысяч до миллионов инструкций, и мы хотели бы использовать передовой опыт в моделировании данных, например, используя базу данных. В подходе, использующем базу данных, мы тяготели бы к фиксированным столбцам и позволяли расширять строки, чтобы захватить переменную информацию (длительность времени и/или инструкции).
По этим причинам я использую следующий подход в этих диаграммах:
Строки расширяются по мере необходимости для учета времени, тогда как столбцы фиксируются для представления фиксированных этапов аппаратного конвейера.
(Я выбрал этот формат как лучший; однако, конечно, есть и другие подходы. Например, мы можем использовать фиксированные столбцы для этапов конвейера и иметь инструкции для измерения строки. Затем ячейки содержат информацию о времени. Все диаграммы, которые я обсуждал, эквивалентны с точки зрения передаваемой информации.)
Перейдем к конкретному примеру. Традиционный пятиэтапный конвейер в стиле MIPS состоит из следующих этапов:
Короткое имя | Расширение | Входы | Блоки | Выходы |
---|---|---|---|---|
ЕСЛИ | Получение инструкций | ПК | ПК, память инструкций | Инструктивное слово |
Я БЫ | Инструкция декодирования | Инструктивное слово | Управление, Регистры | Сигналы управления, значения регистров |
БЫВШИЙ | Исполнение | Регистрировать значения | АЛУ | результат АЛУ |
МЕМ | Память | Адрес памяти | Память данных | Объем памяти |
ВБ | Ответить | Значение для записи | Регистры | н/д |
- IF — извлекает инструкцию из памяти инструкций, используя ПК для адреса слова инструкции для чтения
- ID — декодирует командное слово в управляющие сигналы и использует имена регистров в командном слове для поиска значений регистров.
- EX — выполняет некоторые арифметические операции, такие как ADD или AND
- MEM — доступ к памяти данных для инструкций LOAD или STORE.
- WB — записывает выходные значения в регистры
Стадия WB завершает выполнение инструкции. Другого выхода нет, так как нет следующего этапа. Последовательные программные инструкции взаимодействуют друг с другом через (значения в) регистрах и памяти. Этап WB обычно довольно прост с точки зрения его внутренней логики.
Вам придется изучить конкретную архитектуру процессора, используемого в вашем курсе, чтобы получить правильные ответы. Например, ниже я предположил, что блок регистров внутренне способен к своей собственной пересылке, так что он пересылает любое значение обратной записи на свои выходы в том же цикле. Если это не так, то существует дополнительная опасность. Подробнее об этом смотрите на пузырьковой диаграмме.
Вот пример:
**1 В конце этого цикла (который начинается в t+3, где instr 2: находится в EX) значение a2+64 выходит из ALU, но его еще нет в регистре a0! Кроме того, в конце этого же цикла instr 3: in ID прочитал устаревшие/неверные значения для a0.
**2 Заметим, что запись в регистр (обратная запись) a0 для instr 3: не происходит до этапа WB в момент t+5. Таким образом, регистр, наконец, актуален в начале t+5 (с внутренней переадресацией регистра или t+6 без), что на 2 цикла позже для стадии ID instr 3:, которая начинается в t+3, где он читает регистр a0.
Без байпаса процессору пришлось бы останавливаться, чтобы избежать опасности — эту остановку также называют пузырем в конвейере. Точная природа пузырька зависит от того, как процессор обнаруживает опасность.
(Некоторые процессоры вообще их не обнаруживают, что требует от программистов и компиляторов на ассемблере вставлять инструкции NOP между инструкциями по мере необходимости, чтобы избежать опасностей. Это означает, что такой машинный код сильно зависит от внутренней архитектуры процессора и потребует корректировок. для работы на процессорах с различной конвейерной архитектурой.)
Здесь мы видим, что нормальное чтение регистра для instr 3: произойдет в ID в момент t+3. Чтобы избежать опасности (без какой-либо формы обхода), инструкция будет повторять этап ID до тех пор, пока правильное значение a0 не будет наконец готово, что будет в момент времени t+5. В t+5 instr 2: наконец записывает свое значение обратно в файл регистров, так что к началу t+5 считанное из регистра значение a0 получит актуальное значение (опять же при условии внутренней переадресации файла регистра). Такое избегание опасностей стоило бы 2 циклов, чтобы решить эту проблему. (См. изображение пузырьков и заметок ниже.)
А обходить представляет собой сложную схему, задача которой в конечном счете состоит в том, чтобы выбрать — при абсолютно правильных условиях — либо использовать значения, считанные из регистра, из этапа ID (только если они не устарели), либо переопределить другим значением откуда-то еще (когда реестр устарел).
По сути, обход должен сравнивать имена регистров, используемых в смежных инструкциях (сравнивать целевой регистр предыдущей инструкции с обоими (если они есть) источниками последней инструкции). Если имена регистров совпадают, то указывается обход, поскольку этап ID последней инструкции извлек устаревшее значение регистра.
Ан обход АЛУ подает выходные данные АЛУ обратно на вход АЛУ, чтобы операция АЛУ, только начавшаяся с нового цикла, могла использовать значение, которое она только что вычислила в только что закончившемся цикле, не дожидаясь, пока значение пройдет еще два этапа конвейера, чтобы получить обратно в свой надлежащий регистр.
На схеме обозначим знаком Красная стрелка где здесь должна происходить операция обхода АЛУ.
Заметим, что в этом примере фактическое значение АЛУ готово после EX instr 2: в t+3 — значение a2+64 впервые появляется в процессоре к моменту времени t+4, и, что АЛУ, естественно, хотел бы для вычисления сложения (для режима адресации инструкции загрузки, здесь a0+24), начиная с момента времени t+4.
Если у нас есть обход АЛУ (красная стрелка), мы можем подать выход АЛУ из операции АЛУ t+3 на вход АЛУ в момент t+4. Этот механизм избежит этой опасности, не тратя ни киосков, ни пузырей!
Давайте посмотрим на следующую опасность: опасность LOAD также записывает значение регистра в конце этапа WB, поэтому также имеет задержку в 3 цикла для непосредственно следующей инструкции.
Обход НАГРУЗКИ также будет полезен для производительности. Байпас LOAD будет подаваться на вход ALU для следующего цикла, и значение для этого байпаса поступает со ступени MEM (тогда как значение байпаса ALU поступает со стадии EX).
Поскольку результат операции ЗАГРУЗКИ недоступен до конца этапа МЕМ, байпас здесь сможет исключить только 2 из 3 циклов пузырьков. В дополнение к обходу нагрузки (фиолетовая стрелка), процессор должен будет вставить один цикл остановки, показанный как <bubble>
.
NB: Это, вероятно, два самых важных обхода для иллюстративных целей, но ни в коем случае не единственные.
Филиалы также вызывают проблемы для конвейеров. Всякий раз, когда процессор запускает последовательность инструкций заново, требуется (в нашем примере с 5 этапами конвейера) до 5 циклов, прежде чем мы увидим результаты первой инструкции. После 5 циклов конвейер заполнен, и процессор эффективно перекрывает выполнение нескольких инструкций в конвейере. Таким образом, это означает, что при переключении последовательностей инструкций возникают дополнительные затраты на запуск.
Такие накладные расходы при запуске возникают, когда программа изменяет поток управления по сравнению с тем, который предполагал процессор. Программы изменяют поток управления с помощью циклов и операторов if-then-else, используя инструкции перехода, и, в частности, инструкции условного перехода трудно предсказать, будут ли они переходить или нет, поскольку используемое ими условие является динамическим.
Например, когда процессор предполагает, что условный переход не будет выполнен, а оказывается, что он выполнен, то к тому моменту, когда он узнает об этом, он уже начнет работать над несколькими другими инструкциями, которые уже не актуальны (они находятся на неправильном пути). управлять потоком программы) и должны быть отброшены. Это связано с тем, что конвейерный процессор всегда пытается заполнить канал, а не ничего не делает, ожидая разрешения ветки как принятой или непринятой. Разрешение условных ветвей обычно происходит на этапе EX, поскольку операция сравнения использует схему вычитания ALU. Это означает, что когда условный переход оказывается выполненным там, где процессор предполагал, что этого не будет, на более ранних стадиях, IF и ID, должны быть отброшены инструкции. Эта ситуация будет стоить пузырю в 2 такта, так как процессор перезагружается с новой последовательностью команд.
Следующая диаграмма иллюстрирует вставку NOP, чтобы избежать опасности ALU (только мы не избегаем опасности LOAD). Если сделать так, это будет стоить 2 цикла.
Опять же, мы предполагаем, что блок регистров имеет внутреннюю пересылку, так что он может выводить значение обратной записи в том же цикле (здесь t+5) при использовании следующей инструкцией. Это правдоподобно, потому что, в отличие от всех других стадий, стадия WB не нужно вычислять никаких значений — ему нужно только сохранить/скопировать существующий, и эти операции намного быстрее, чем арифметика или доступ к памяти.
Если бы блок регистров не имел внутренней переадресации, то потребовался бы третий NOP, чтобы полностью избежать показанной здесь опасности ALU.