В компьютерной архитектуре предсказатель ветвления представляет собой цифровую схему, которая пытается угадать, к какой ветке (например, структура if-then-else) будет идти, прежде чем это будет известно наверняка. Целью прогнозирования ветвей является улучшение потока в конвейере команд. Отраслевые предиктора играют решающую роль в достижении высокой эффективности во многих современных конвейерных микропроцессорных архитектурах, таких как x86.

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


В компьютерной архитектуре предиктор ветвления - это цифровая схема, которая пытается угадать, каким образом пойдет ветвь (например, структура if-then-else), прежде чем это станет известно наверняка. Целью предиктора ветвления является улучшение потока в конвейере команд.

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

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

Точно неизвестно, будет ли выполнен условный переход или нет, пока условие не будет вычислено и условный переход не пройдет этап выполнения в конвейере команд.

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

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

Источник: http://en.wikipedia.org/wiki/Branch_predictor


Уязвимость безопасности Spectre вращается вокруг предсказания ветвлений:


Другие источники

Предикторы специального назначения: стек адреса возврата для вызова/возврата. ret фактически является косвенной ветвью, устанавливающей счетчик программы = адрес возврата. Само по себе это было бы трудно предсказать, но вызовы обычно выполняются со специальной инструкцией, поэтому современные процессоры могут сопоставлять пары вызова/возврата с внутренним стеком.

Детали компьютерной архитектуры о прогнозировании ветвлений/спекулятивном исполнении и его влиянии на конвейерные процессоры

  • Почему обрабатывать отсортированный массив быстрее, чем несортированный?
  • Предсказание ветвлений - статья Дана Луу о предсказании ветвлений, адаптированная из беседы. С диаграммами. Хорошее введение в то, зачем это нужно, и некоторые базовые реализации, используемые в ранних процессорах, позволяющие создавать более сложные предикторы. И, наконец, ссылка на предикторы веток TAGE, используемые в современных процессорах Intel. (Слишком сложно для этой статьи, чтобы объяснить, хотя!)
  • Медленная jmp-инструкция - даже безусловные прямые переходы (например, x86 jmp) необходимо прогнозировать, чтобы избежать остановок на самой первой стадии конвейера: выборка блоков машинного кода из I-кэша. После извлечения одного блока вам необходимо знать, какой блок следует выбрать следующим, до (или в лучшем случае параллельно) декодирования блока, который вы только что получили. Большая последовательность jmp next_instruction предсказание ветвлений и обнажит стоимость неправильного предсказания в этой части конвейера. (Многие высокопроизводительные современные процессоры имеют очередь после выборки перед декодированием, чтобы скрыть пузырьки, поэтому некоторые блоки не ветвящегося кода могут позволить пополнению очереди.)
  • Предсказание цели ветвления в сочетании с предсказанием ветвления?
  • Какое неверное предсказание ветвления обнаруживает целевой буфер ветвления?

Стоимость ветки мисс


Современные предикторы TAGE (например, в процессорах Intel) могут "изучать" удивительно длинные шаблоны, поскольку они индексируются на основе прошлой истории ветвей. (Таким образом, одна и та же ветвь может получать разные предсказания в зависимости от пути, по которому она идет. Одна ветвь может иметь свои данные предсказания, разбросанные по многим битам в таблице предикторов ветвления). Это имеет большое значение для решения проблемы непрямых ветвлений в интерпретаторе, почти всегда неверно предсказывающего (оптимизация предварительной выборки в X86: многопоточный код " computed goto" и предсказание ветвлений и производительность интерпретаторов - не верьте фольклору), или, например, двоичный файл поиск по одним и тем же данным с одинаковыми данными может быть действительно эффективным.

Статическое предсказание ветвления на более новых процессорах Intel - согласно экспериментальным данным, кажется, Nehalem и ранее иногда используют статическое предсказание в какой-то момент в конвейере (обратные ветки по умолчанию предполагаются как принятые, впереди не приняты). Но Sandybridge и новее кажутся быть всегда динамичным, основанным на некоторой истории, будь то из этой ветки или из-за того, что это псевдоним. Почему Intel изменила механизм прогнозирования статических ветвлений за эти годы?

Случаи, когда TAGE делает "удивительно" хорошо


Компоновка кода сборки: не столько для предсказания ветвлений, сколько потому, что не взятые ветвления проще в интерфейсе, чем взятые ветвления. Лучшая плотность кода I-кэша, если быстрый путь - это просто прямая линия, а выделенные ветки означают, что часть блока выборки после ветки бесполезна.

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


Код без ветвей: использование cmov или других трюков, чтобы избежать веток

Это asm эквивалент замены if (c) a=b; с a = c? b: a; a = c? b: a; , Если b не имеет побочных эффектов и a не является потенциально разделяемой ячейкой памяти, компиляторы могут выполнить "if-преобразование", чтобы выполнить условие с зависимостью данных от c вместо зависимости управления.

(Компиляторы C не могут вводить неатомарное чтение/запись: это может привести к изменению переменной в другом потоке. Запись вашего кода как всегда переписывания значения говорит компиляторам, что это безопасно, что иногда включает автоматическую векторизацию: AVX-512 и ветвление)

Потенциальный недостаток cmov в скалярном коде: зависимость данных может стать частью цепочки зависимостей, переносимых циклами, и стать узким местом, в то время как прогнозирование ветвлений + спекулятивное выполнение скрывают задержку зависимостей управления. Зависимость данных без ответвлений не предсказана и не спекулирована, что делает ее полезной для непредсказуемых случаев, но потенциально может быть и плохой.

  • https://yarchive.net/comp/linux/cmov.html - Линус Торвальдс объясняет, почему cmov часто отстой: большинство ветвей предсказуемы, а ветвь даже вычисляет условие ветвления вне критического пути.
  • Флаг оптимизации gcc -O3 делает код медленнее, чем -O2 - Анализ реального случая, когда эвристика if-преобразования GCC не ожидает отсортированных данных, а более длинная цепочка деп с cmov с cmov создает узкое место.