На лекции мы пришли к выводу, что если выполнение инструкций в однотактном процессоре лишь последовательно задействует его функциональные блоки (то есть в каждый момент времени задействован только один из них, а остальные ожидают), то разумным шагом будет поставить между ними буферные регистры, назвать это ступенями и одновременно, как на конвейере (да хоть конвейер по производству останкинских сосисок себе представь — одна суть), обрабатывать несколько подряд идущих инструкций, каждая на своей ступени. Хотя каждой отдельно взятой инструкции надо пройти все стадии конвейера, то есть выполнение происходит за несколько тактов, команды «сходят» с конвейера на каждом такте. Время выполнения одной инструкции называется латентностью. Скорость обработки инструкций называется пропускной способностью конвейера. Ниже приводится сравнение работы однотактного и конвейерного процессора.
Латентность инструкций в конвейерном процессоре выше, чем у однотактного процессора, то есть одна отдельно взятая инструкция выполняется дольше, чем, например, в однотактном процессоре. Однако, пропускная способность конвейера гораздо выше, чем в однотактной микроархитектуре, так как на каждом такте заканчивает выполняться очередная инструкция.
Критический путь у такой реализации короче однотактной, но длиннее многотактной, однако, по производительности это решение наиболее успешное.
На лекции был реализован классический конвейер, состоящий из 5 стадий (ступеней):
- Fetch (выборка инструкции из памяти программ. Включает в себя PC и Instruction Memory)
- Decode (дешифрация инструкции и подготовка операндов. Включает в себя Main Decoder, Register File и блоки знакорасширения, подготавливающих константы)
- Execute (выполнение инструкции. Включает в себя мультиплексоры и ALU)
- Memory (обращение к памяти данных. Включает в себя Data Memory)
- Writeback (запись результата в регистровый файл. Включает в себя мультиплексор и порт записи Register File)
Несмотря на главный плюс конвейерной реализации (скорость), ее главным минусом является необходимость устранения конфликтов. Конфликт конвейера — это ситуация, при которой конвейер должен приостановиться, чтобы выполнение очередной инструкции не нарушило работу программы. Они возникают из-за параллельного выполнения нескольких инструкций на разных стадиях конвейера, так как из-за зависимостей не любые из них могут обрабатываться параллельно. Например, типичным конфликтом конвейера является конфликт по данным, который может возникнуть, если очередная инструкция пытается считать данные из регистрового файла, которые предшествующая инструкция еще не успела там разместить.
Указанный конфликт решается переброской результата операции с более поздних ступеней назад, чтобы этим результатом можно было воспользоваться до того, как он окажется в регистровом файле. Данный подход не помогает при инструкциях обращения к памяти, так как считываемый операнд может потребоваться до того, как он будет считан из памяти. В таком случае приходится приостанавливать конвейер и очищать стадий, в которые были загружены недостоверные данные. Ситуация, в которой в конвейер помещают нули (очищают стадии) называется пузырьком.
Разрешением конфликтов занимается блок устранения конфликтов (Hazard Unit), который в автоматическом режиме их обнаруживает и предпринимает необходимые действия по их устранению.
Существуют три вида конфликтов конвейера:
- Структурные (вызванные несовершенностью аппаратной части, при которой образуется нехватка ресурсов, то есть нескольким стадиям приходится делить один ресурс между собой, из-за чего кому-то приходится ждать, пока он не освободиться, а значит приостанавливать работу). Минимизация таких конфликтов реализуется усовершенствованием структуры устройства
- По данным (вызванные зависимостью по данным между несколькими соседними инструкциями). Существует три типа конфликтов по данным:
- RAW (read after write — чтение после записи, при котором новая инструкция пытается получить значение из памяти, которая предыдущая инструкция еще не успела туда записать). Разрешается, переброской результата или методом пузырька (приостановкой конвейера)
- WAR (write after read — запись после чтения, при котором новая инструкция пытается разместить данные в памяти до того, как старая инструкция успела их оттуда считать). Конфликт возникает в системах с внеочередным исполнением команд, то есть в таких, где заданная программистом последовательность инструкций может быть изменена с целью увеличения производительности. Разрешается конфликт, например, методом пузырька или переименовыванием регистров
- WAW (write after write — запись после записи, при котором более ранняя инструкция размещает значение в памяти позже, чем более поздняя инструкция, тем самым нарушая порядок записи в память). Разрешается конфликт так же как и в конфликтах типа WAR.
- По управлению (вызванный неоднозначностью того, какая инструкция должна быть загружена после инструкции условного перехода, так как результат перехода будет известен только на стадии Execute, а загружать новую инструкцию надо уже, когда команда условного перехода будет на стадии Decode). Конфликт разрешается методом пузырька, либо предположением о том, произойдет переход или нет. В случае успешного предсказания потери производительности не происходит. В случае неверного предсказания, ступени конвейера, в которые были загружены неправильные команды должны очиститься.
В среднем, каждая 7 инструкция в программе является инструкцией условного перехода. Поэтому конфликты по управлению сильнее всего влияют на производительность конвейерного процессора.
Разработанный на лекции конвейерный процессор не устраняет конфликты по управлению, следовательно является недоработанным, функционирует неправильно и рассматривался только в качестве примера.
- Ссылка на видеозапись лекции
- Пример проектирования конвейерного процессора с похожей архитектурой (MIPS вместо RISC-V) [Харрис и Харрис. Цифровая схемотехника и архитектура компьютера — весь параграф 7.5]
- Еще один пример с конвейером от тех же авторов, но на примере архитектуры ARM [Харрис и Харрис. Цифровая схемотехника и архитектура компьютера. Дополнение по архитектуре ARM — весь параграф 2.5]
- Тот же разбор MIPS, что из основных материалов, но от отцов RISC и с более подробным обсуждением материала, однозначно очень полезно для ознакомления. И рисунков там больше [Паттерсон и Хеннесси. Архитектура компьютера и проектирование компьютерных систем — параграфы 4.5 — 4.8]