Какова связь между переупорядочением команд, выполняемым компилятором, и переупорядочением команд, выполняемым процессором? - PullRequest
0 голосов
/ 18 января 2019

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

machine_instruction_1
machine_instruction_2
machine_instruction_3
machine_instruction_4
machine_instruction_5

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

machine_instruction_5
machine_instruction_4
machine_instruction_3
machine_instruction_2
machine_instruction_1

Пока все хорошо.

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

  • первый из-за оптимизации компилятора
  • второй из-за неправильного выполнения процессора

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

1 Ответ

0 голосов
/ 18 января 2019

При рассмотрении выполнения инструкций необходимо соблюдать семантику программы . Любой порядок правильный, если это соблюдается. Конкретно, это описывается «зависимостями», которые указывают, требуют ли некоторые инструкции заданного порядка относительно правильного поведения программы. Например, рассмотрим следующую программу

1 x <= y+3
2 z <= 2*x
3 w = 5*y
4 y = 2*a

Инструкции 1 и 2 являются зависимыми. Если их относительный порядок изменяется, программа не соответствует желаемому программисту, и любое изменение порядка запрещено. По разным причинам 4 нельзя выполнить без изменений, пока y не будет использоваться 1 и 3. Существуют различные виды зависимостей, в том числе при рассмотрении потока управления.

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

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

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

Таким образом, нет конкуренции между компилятором и процессором, но есть эффективное сотрудничество.

...