Перейти к содержанию
    

процессор сам меняет местами строки кода

https://www.youtube.com/watch?v=SIZmLPtcZiE&t=1112s

 

начало: 10:24

10:54 - "Хитрый процессор" может взять и переставить инструкции местами.

 

КАК?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

начало: 10:24

10:54 - "Хитрый процессор" может взять и переставить инструкции местами.

КАК?

А что не понятного? Современные x86 внутри вроде как могут распараллеливать выполнение инструкций. Если между ними нет взаимозависимостей.

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

Для борьбы с этим (когда нужно) уже даже в Cortex-M ввели инструкции барьеров.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

https://www.youtube.com/watch?v=SIZmLPtcZiE&t=1112s

начало: 10:24

10:54 - "Хитрый процессор" может взять и переставить инструкции местами.

КАК?

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

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

Если не знать и не понимать этих механизмов - рассуждения на эту тему превращаются в сплошное дилетантство... ;)

P.S. Если Вы пишите на ассемблере, и модифицируете инструкции " впереди себя", то результат будет зависеть от длины конвейера и его текущей загруженности в данный момент...

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

https://www.youtube.com/watch?v=SIZmLPtcZiE&t=1112s

 

начало: 10:24

10:54 - "Хитрый процессор" может взять и переставить инструкции местами.

 

КАК?

Я это видео не смотрел... :)

Но точно знаю, как делается для Аналоговских DSP.

Значит хитрость вот какая может быть.

Представим:

инстр1

инстр2

инстр3

джамп...

 

Как это обычно выполняется?

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

А теперь представим, что команду "джамп" компилятор передвинет вперед на то кол-во инструкций, какова глубина конвейера.

Как-то так:

инстр1

инстр2

джамп

инстр3..

 

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

И об этом у Аналога была статья с примерами...

Ну а дальше если речь идет об оптимизирующем компиляторе, то надо читать об статическом и динамическом предсказании переходов...

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...

Ну а дальше если речь идет об оптимизирующем компиляторе, то надо читать об статическом и динамическом предсказании переходов...

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

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

В итоге, обеспечивается максимальное быстродействие...

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

В итоге, обеспечивается максимальное быстродействие...

Ну да...

А если там еще есть микро-архитектура, это когда программист думает, что "вот по этому адресу есть регистр общего назначения"... А на самом деле, этих регистров там несколько и только компилятор знает, в каком хранится какое значение от предыдущих шагов программы. Поэтому к таким процессорам ассемблера нет вообще. У Шарков еще был, а у Блэкфинов - уже нет... И что там на самом деле делает процессор - тайна :)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Поэтому к таким процессорам ассемблера нет вообще. У Шарков еще был, а у Блэкфинов - уже нет... И что там на самом деле делает процессор - тайна :)

Если есть GCC, то есть и Асм. Вот только отдельно его может не быть потому как даром не нужен.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не следует путать оптимизации конвейера и изменение порядка следования инструкций в процессоре. Первое выполняется компилятором на этапе компиляции - компилятор анализирует код и оптимизирует поток инструкций так, чтобы было как можно меньше простоев конвейера. Это то, что описал iosifk. Эта ситуация ярко проявляется на том же Blackfin'е. Процессор точно выполняет этот [оптимизированный] поток инструкций, никакой его самодеятельности тут нет - всё, что видно по листингу, будет исполняться процессором именно так. И, конечно, ничего не мешает писать тут на ассемблере, просто для достижения скорости вам придётся тоже переставлять инструкции, чтобы избежать stall'ов конвейера.

 

Более сложные процессорные ядра (современные x86, Cortex-A) поддерживают аппаратные оптимизации потока выполнения - т.е. могут менять физическое выполнение программы. Сюда относятся, в частности, изменение порядка следования инструкций (instruction reordering) и переименование регистров (register renaming). Как уже было сказано выше, если конвейер процессора получает инструкции на вход, которые не связаны по контексту друг с другом (т.е. нет взаимных связей), то процессор может поменять порядок их выполнения.

 

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

 

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

 

Это очень упрощенный пример, в реальности там ещё много факторов, которые влияют на порядок выполнения инструкций.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Если компилятор знает, то будет знать и программист, пишущий на асме. Особых сложностей в этом нет. Ещё больше 10 лет назад писал на асме для TMS320VC5502: и уже там я распараллеливал поток инструкций - держал в голове что например одна инструкция (из пары) у меня выполняется на D-unit АЛУ, а вторая (из пары) - на A-unit АЛУ, поэтому они не должны использовать общие ресурсы (регистры), так как операции для этих разных АЛУ выполняются на разных стадиях конвеера и если будут взаимозависимости, то могут быть штрафы по нескольку тактов (на величину разности по конвееру между фазами исполнения разных инструкций).

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

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

Запись значений из регистров в память в ядрах C55xx всегда выполняется строго в одной и той же фазе конвеера. А именно об этом идёт речь в том видео, а не о реальной стадии конвеера на котором выполнится команда! Так что - вне зависимости от точки выполнения на конвеере, данные в память на C55xx всегда пишутся строго в том порядке, в каком стоят команды. Не знаю как с этим обстоят дела на других ядрах...

Но дальше идут кеши и разные регионы памяти, к каждому из которых своя шина, и каждый из которых может быть занят или не занят в этот момент другим bus-master-ом. Вот тут как раз вполне возможно рассогласование времён физической записи в ячейку памяти.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...