Подтвердить что ты не робот

Современная модель затрат x86

Я пишу компилятор JIT с бэкэндом x86 и изучаю ассемблер x86 и машинный код, когда я иду. Я использовал ARM-ассемблер около 20 лет назад и удивлен различием моделей затрат между этими архитектурами.

В частности, обращения к памяти и ветки дороги в ARM, но эквивалентные операции стека и скачки дешевы на x86. Я считаю, что современные процессоры x86 делают гораздо более динамическую оптимизацию, чем ядра ARM, и мне трудно предвидеть их эффект.

Что такое хорошая модель затрат, которую нужно учитывать при написании ассемблера x86? Какие комбинации инструкций дешевы и дороги?

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

Я еще не делал плавающей запятой, но я хотел бы скоро перейти к ней. Есть ли что-то неявное в отношении взаимодействия нормального и плавающего кода?

Я знаю, что есть множество ссылок (например, Майкл Абраш) на оптимизацию x86, но у меня есть предчувствие, чем что-то большее, чем несколько лет, не будет применяться к современным процессорам x86, потому что они в последнее время сильно изменились. Правильно ли я?

4b9b3361

Ответ 1

Лучшей ссылкой является Руководство по оптимизации Intel, в котором содержится довольно подробная информация об архитектурных опасностях и задержках команд для всех последних ядер Intel, а также как большое количество примеров оптимизации.

Еще одна отличная рекомендация - ресурсы оптимизации Agner Fog, которые имеют также и покрытие ядер AMD.

Обратите внимание, что конкретные модели затрат по своей природе специфичны для микроархитектуры. Нет такой вещи, как "модель стоимости x86", которая имеет какую-либо реальную действительность. На уровне инструкций характеристики производительности Atom сильно отличаются от i7.

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

Ответ 2

Torbjörn Granlund Задержки и пропускная способность для процессоров AMD и Intel x86 тоже хороша.

Изменить

Документ Granlund относится к пропускной способности команд в контексте того, сколько команд определенного типа может быть выпущено за такт (i e выполняется в параллельном режиме). Он также утверждает, что документация Intel не всегда точна.

Ответ 3

Для чего стоило, была замечательная книга под названием "Внутренние петли" Рика Бута, которая подробно описала, как вручную микро-оптимизировать код сборки IA-86 для процессоров Intel 80486, Pentium, Pentium Pro и Pentium MMX с множеством полезных примеров кода реального мира (хеширование, перемещение памяти, генерация случайных чисел, сжатие Хаффмана и JPEG, умножение матрицы).

К сожалению, книга не обновлялась со времени ее первой публикации в 1997 году для более новых процессоров и архитектур процессоров. Тем не менее, я бы по-прежнему рекомендовал его как нежное введение в такие темы, как:

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

Ответ 4

Стоит посмотреть на существующие компиляторы с открытым исходным кодом, такие как GCC и LLVM. Они имеют модели для затрат на обучение, а также достойные (но идеализированные) модели машин (например, ширина выпуска, размеры кеша и т.д.).

Ответ 5

Конечно, отчеты Agner Fog и справочное руководство по оптимизации архитектуры Intel® 64 и IA-32 являются необходимыми и отличными рекомендациями. AMD также имеет руководство по оптимизации:

  • Руководство по оптимизации программного обеспечения для процессоров AMD 15h

Однако для понимания кодовых последовательностей необходимы два инструмента Intel:

  • Анализатор кода архитектуры Intel®
  • Intel® VTune ™

IACA - ваша модель затрат. Я использую его на OSX, но VTune работает только в Windows и Linux.

Вы также можете вникнуть в патентную литературу Intel и различные документы Intel, чтобы лучше понять, как все работает:

  • Микроархитектура Intel Core следующего поколения
  • Хасуэлл: процессор Intel Core 4-го поколения
  • Кэш микроопераций: внешний интерфейс для переменной длины инструкции ISA

Ответ 6

Я пишу компилятор JIT с бэкэном x86 и обучением x86 ассемблер и машинный код, когда я иду.

Существенная проблема заключается в том, что компилятор JIT не может позволить себе потратить огромное количество времени на микро-оптимизацию. Поскольку "оптимизация" происходит во время выполнения, затраты на оптимизацию должны быть меньше времени, сохраненного оптимизацией (в противном случае оптимизация становится чистой потерей производительности).

Для 80x86 существует несколько разных процессоров с различным поведением/характеристиками. Если вы учитываете фактические характеристики ЦП, то стоимость оптимизации будет возрастать, и вы захлопнитесь прямо в барьер "стоить больше, чем вы". Это особенно верно для таких вещей, как "идеальное планирование команд".

К счастью, большинство (но не все) современных процессоров 80x86 имеют различные функции (внеочередное, спекулятивное выполнение, гиперпоточность), чтобы смягчить (некоторые из) затраты на производительность, вызванные "менее совершенной" оптимизацией. Это, как правило, делает дорогие оптимизации менее полезными.

Первое, что вам нужно сделать, это определить, какие фрагменты кода следует оптимизировать, а какие - нет. Вещи, которые не выполняются часто (например, "только один раз", код инициализации) не должны оптимизироваться вообще. Это только часто исполняемые части (например, внутренние петли и т.д.), Где это стоит беспокоить. Как только вы определили фрагмент, который стоит оптимизировать вопрос, он становится "сколько?".

В качестве грубого обобщения; Я ожидал бы, что (в среднем) 90% кода вообще не стоит оптимизировать, а для 9% кода стоит только сделать некоторую общую оптимизацию. Оставшиеся 1% (которые могут извлечь выгоду из обширной оптимизации в теории) в конечном итоге станут слишком сложными для разработчиков JIT-компилятора, которые будут практиковаться на практике (и приведут к огромному кошмару сложности/проверяемости - например, "ошибки, которые существуют только тогда, когда работающих на некоторых процессорах".