Последовательность выполнения процессора

Обновлено: 03.07.2024

На следующей диаграмме примерно представлена ​​общая модель основных компонентов компьютера, которую вы должны иметь в виду:

Расписание инструкций

  • Это не может повлиять на микроархитектуру; он должен иметь дело только с ISA. Он может использовать свои знания о микроархитектуре для разумного планирования, но может лишь косвенно влиять на то, что происходит во время выполнения.
  • При изменении микроархитектуры планировщик должен быть переписан для учета новых деталей. Теоретически старые программы следует перекомпилировать, но на практике ОС и другое программное обеспечение часто распространяются с двоичными файлами, оптимизированными для более старой версии архитектуры, чтобы избежать несовместимости.
  • Компилятору приходится иметь дело с неравномерными задержками и неоднозначностью псевдонимов, вызванными наличием системы памяти. Компилятор может только догадываться о том, что будет происходить во время выполнения, но не может фактически наблюдать за поведением во время выполнения с точностью, позволяющей лучше планировать.

Выполнение вне очереди

Конвейеры, которые мы изучали до сих пор, были статически запланированными и неупорядоченными конвейерами. То есть инструкции выполняются в порядке программы. Если опасность вызывает циклы остановки, то все инструкции до инструкции-нарушителя останавливаются до тех пор, пока опасность не исчезнет. Как мы видели, переадресация, прогнозирование ветвлений и другие методы могут уменьшить количество необходимых нам циклов простоя, но иногда простоя не избежать. Например, рассмотрим следующий код: Предположим, что r3 и r5 готовы в регистровом файле. Предположим также, что инструкция загрузки отсутствует в кэше данных L1, поэтому блоку загрузки требуется около 20 циклов, чтобы извлечь данные из кэша L2. Во время работы нагрузочной установки трубопровод останавливается. Обратите внимание, однако, что вторая инструкция добавления не зависит от значения r1; он может выдаваться и выполняться, но детали нашего неупорядоченного конвейера препятствуют этому из-за задержки. Функциональный блок, который должен складывать вместе r3 и r5, вместо этого бездействует, ожидая завершения загрузки, чтобы можно было декодировать инструкцию add. и выпущено.

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

Реализация внеочередного выполнения

Чтобы внедрить процессор OoO, конвейер должен быть улучшен, чтобы отслеживать дополнительную сложность. Например, теперь, когда мы можем переупорядочивать инструкции, у нас могут быть опасности WAR и WAW, о которых нам не нужно беспокоиться с неупорядоченным конвейером. Эта диаграмма иллюстрирует основную идею:

  • Зарегистрируйте переименование. Регистры, которые являются адресатами результатов команд, переименовываются, т. е. в аппаратном обеспечении может использоваться более одной версии этого имени регистра. (Это можно сделать в компиляторе, но только с архитектурно видимыми регистрами; это гораздо более мощная техника при аппаратной реализации.) Это можно сделать на новом этапе конвейера «переименования регистров», который выделяет физические (т.е. реальные) регистры. к экземплярам логических (т.е. ISA) регистров с помощью таблицы псевдонимов регистров, которая также отслеживает «свободный список» доступных физических регистров. Или же переименованные регистры могут быть предоставлены неявно с помощью станций резервирования (или и того, и другого). Мы пока поговорим о станциях резервирования.
  • Окно инструкций. Этот буфер содержит инструкции, которые были выбраны и декодированы и ожидают выполнения. Примечание. Часто окно инструкций на самом деле не существует в виде единого буфера, а распределено между станциями резервирования (см. ниже).
  • Усовершенствованная логика задач. Логика выдачи должна быть улучшена, чтобы выдавать инструкции не по порядку в зависимости от их готовности к выполнению.
  • Станции бронирования. С каждым функциональным блоком связан набор станций резервирования. Каждая станция содержит информацию об инструкциях, ожидающих или готовых к выдаче. Станции резервирования также можно использовать в качестве физического механизма переименования регистров.
  • Загрузить/сохранить очередь. Это похоже на наличие станций резервирования для блока памяти, но со специальными свойствами, чтобы избежать опасности данных через память.
  • Подсчет очков или алгоритм Томасуло. Это алгоритмы, которые отслеживают детали конвейера, решая, когда и что выполнять.Табло знает (или предсказывает), когда результаты инструкций будут доступны, поэтому оно знает, когда зависимые инструкции могут выполняться и когда они могут записывать свои результаты в регистры назначения. В алгоритме Томасуло станции резервирования используются для неявной реализации переименования регистров. (Другие схемы добавляют фактический файл физического регистра и таблицу псевдонимов регистров для выполнения переименования, что позволяет новой схеме устранить больше опасностей данных.)
  • Общая шина данных (CDB). Общая шина данных — это сеть между функциональными блоками, используемая для передачи таких вещей, как операнды и теги станций резервирования.
    (Все это из главы 2)
  1. Проблема:
    • Выборка. Блок выборки хранит инструкции в очереди инструкций в программном порядке (т. е. в порядке поступления). Эти инструкции извлекаются с помощью прогнозирования ветвлений. На этапе выдачи инструкция удаляется из этой очереди.
    • Расшифровать. Инструкция декодируется, чтобы определить, какие функциональные блоки ей потребуются.
    • Выделить станцию ​​резервирования. Если в функциональном блоке, который требуется этой инструкции, есть станция резервирования, отправьте ее туда; в противном случае остановите только эту инструкцию из-за структурной опасности.
    • Чтение операндов. Если операнды для инструкции доступны, отправьте их на станцию ​​резервирования для этой инструкции. В противном случае отправьте информацию об источнике этих операндов на станцию ​​резервирования, которая будет ждать операнды. Эта информация представлена ​​в виде тегов, обозначающих функциональные блоки и другие станции бронирования.
    • Переименовать регистры. Неявным образом, отправляя теги вместо имен регистров на станции резервирования, этап выдачи переименовывает регистры в виртуальный набор регистров. Например, опасность WAW больше невозможна, так как один и тот же регистр в двух разных инструкциях соответствует двум разным станциям резервирования.
  2. Выполнить. На станции резервирования по данной инструкции могут быть предприняты следующие действия:
    • Дождитесь операндов. Если есть операнды, которые еще не были вычислены, дождитесь их прибытия, прежде чем использовать функциональный блок. На данный момент инструкция «выдана» со ссылками на то, откуда будут поступать операнды, но без значений.
    • Получить операнды. Когда значение становится доступным из зависимой инструкции, поместите его на станцию ​​резервирования.
    • Вычислить. Когда все операнды присутствуют на станции резервирования, используйте функциональный блок для вычисления результата этой инструкции. Если более чем одна станция резервирования внезапно получает все свои операнды, функциональный блок использует некоторый алгоритм, чтобы выбрать, какая станция резервирования будет вычисляться первой. Обратите внимание, что здесь мы используем ILP; в одном и том же тактовом цикле каждый функциональный блок может независимо выполнять команду из своего набора станций резервирования.
    • Загрузить/сохранить. На самом деле не имеет значения, какая станция резервирования «срабатывает» первой, если только функциональным блоком не является блок памяти, и в этом случае загрузка и сохранение выполняются в порядке программы. Загрузка и сохранение выполняются в два этапа: вычисление эффективного адреса и использование блока памяти. Загрузки могут пойти, как только освободится блок памяти. Сохранения, как и другие инструкции со значениями операндов, ждут, пока значение станет доступным, прежде чем пытаться получить блок памяти.
  3. Запишите результат. Как только результат выполненной инструкции становится доступным, транслируйте его по CDB. Станции резервирования, ожидающие результата этой инструкции, могут продвигаться вперед. На этом этапе также выполняются операции сохранения в память.

Станции бронирования

  • Соч. Операция для выполнения. Этот код относится к функциональному блоку, с которым связана данная станция резервирования. Например, набор значений Op для арифметико-логического функционального блока может быть <Сложение, Вычитание, Отрицание, И, Или, Не >. Для блока памяти набор значений может быть .
  • Qj, Qk. Это теги для станций резервирования, которые будут производить Sj и Sk соответственно. Нулевое значение указывает, что соответствующий источник уже получил свое значение от станции резервирования.
  • Вж, Вк. Это фактические значения исходных операндов. Значение здесь действительно только в том случае, если соответствующая запись Q равна нулю, что указывает на получение исходного значения.
  • А. Содержит эффективный адрес для загрузки или сохранения. Первоначально он может содержать только непосредственное поле инструкции, пока не произойдет вычисление эффективного адреса (напомним, что загрузка и сохранение выполняются в два этапа: вычисление советника и использование блока памяти).
  • Занят. Это логическое условие имеет значение True, если станция бронирования занята, и False, если она свободна.

Пример

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

Вот как будут выглядеть станции резервирования: А вот как будет выглядеть поле Qi для файла регистров с плавающей запятой:

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

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

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

Ситуация следующая:

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

Адрес памяти, где находится первая инструкция, копируется в программный счетчик.

ЦП отправляет адрес счетчика команд в память по адресной шине.

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

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

ЦП выполняет инструкцию в регистре инструкций.

Шаги 3, 4 и 5 называются файлом . Обратите внимание, что шаги 3–7 составляют цикл, файл . Это показано графически на рисунке 8.4.1.

Инструкция wfi («ожидание прерывания») переводит ЦП в состояние ожидания, в котором он остается до тех пор, пока устройство ввода-вывода не отправит ЦП сигнал прерывания. Мы очень кратко рассмотрим прерывания в главе 17, но подробности выходят за рамки этой книги. Пока достаточно понять, что инструкция wfi останавливает цикл выполнения программы.

На самом деле ARM получает две инструкции одновременно. Но это деталь реализации, помогающая ускорить выполнение программы. Логический поток программы соответствует циклу выполнения инструкции, показанному на рис. 8.4.1.

В связи с этим возникает несколько вопросов:

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

An используется для создания .

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

А или используется для создания .

Компилятор или ассемблер переводит язык программирования в исходном файле в битовые шаблоны, которые может использовать ЦП (машинный язык). Содержимое исходного файла остается неизменным.

A используется для создания .

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

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

Возможно, вы использовали интегрированную среду разработки (IDE), например, Microsoft Visual Studio® или Eclipse™, который объединяет все эти три программы в один пакет, где каждый из промежуточных шагов выполняется автоматически. Вы используете программу-редактор для создания исходного файла, а затем даете команду запуска в IDE. IDE скомпилирует программу в ваши исходные файлы, свяжет полученные объектные файлы с необходимыми библиотеками, загрузит полученный исполняемый файл в память, а затем запустит вашу программу. Как правило, промежуточные объектные файлы, полученные в результате компиляции каждого исходного файла, автоматически удаляются с диска.

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

Компьютер представляет собой сложную систему, состоящую из множества различных компонентов. Но в сердце — или, если хотите, в мозгу — компьютера находится единственный компонент, который выполняет фактические вычисления. Это центральный процессор или центральный процессор. В современном настольном компьютере ЦП представляет собой один «чип» размером порядка одного квадратного дюйма. Работа процессора заключается в выполнении программ.

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

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

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

ЦП содержит арифметико-логическое устройство или АЛУ, которое является частью процессора и выполняет такие операции, как сложение и вычитание. Он также содержит небольшое количество регистров, которые представляют собой небольшие блоки памяти, способные хранить одно число. Типичный ЦП может иметь 16 или 32 регистра «общего назначения», в которых хранятся значения данных, которые сразу доступны для обработки, и многие инструкции машинного языка ссылаются на эти регистры. Например, может быть инструкция, которая берет два числа из двух указанных регистров, складывает эти числа (используя АЛУ) и сохраняет результат обратно в регистр. И могут быть инструкции для копирования значения данных из основной памяти в регистр или из регистра в основную память.

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

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

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

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

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

Насколько я понимаю, ЦП изменяет порядок операций, которые прописаны в машинном коде, для оптимизации, и это называется внеочередным выполнением.

В термине "порядок памяти" он определяет порядок доступа к памяти. Например, в расслабленном порядке он определяет очень слабые правила упорядочения, и изменение порядка выполнения легко происходит.
Есть некоторые модели упорядочения памяти, такие как TSO в x86. В такой модели упорядочения памяти определяется семантика порядка доступа процессора к памяти.

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



1 Ответ 1

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

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

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

Читайте также: