Действительно ли возможно сказать предиктор ответвления, как, вероятно, это должно следовать за ответвлением?

Смотрите на ContextSingletonBeanFactoryLocator. Это обеспечивает статические средства доступа для овладения контекстами Spring, предполагая, что они были зарегистрированы определенными способами.

Это не симпатично, и более сложно, чем, возможно, Вы хотели бы, но это работает.

73
задан Peter Cordes 5 December 2018 в 06:53
поделиться

7 ответов

Да. http://kerneltrap.org/node/4705

__ builtin_expect - это метод, который gcc (версии> = 2.96) предлагают для программисты указать ветку информация о прогнозе компилятор. Возвращаемое значение __ builtin_expect - первый аргумент (который может быть только целым числом) передано ему.

if (__builtin_expect (x, 0))
                foo ();

     [This] would indicate that we do not expect to call `foo', since we
     expect `x' to be zero. 
57
ответ дан 24 November 2019 в 12:17
поделиться

Да, но это не повлияет на . Исключениями являются более старые (устаревшие) архитектуры до Netburst, и даже тогда они не делают ничего измеримого.

Существует код операции «подсказка ветвления», введенный Intel в архитектуре Netburst, и прогнозирование статического ветвления по умолчанию для холодных переходов (назад предсказано принято, вперед предсказано не принято) на некоторых старых архитектурах. GCC реализует это с помощью __ builtin_expect (x, prediction) , где прогноз обычно равен 0 или 1. Код операции, выдаваемый компилятором, игнорируется на всех новых архитектурах процессоров (> = Core 2). Небольшой угловой случай, когда это действительно что-то дает, - это случай холодного скачка на старой архитектуре Netburst. Intel рекомендует сейчас не использовать статические подсказки ветвления, вероятно потому, что они считают увеличение размера кода более вредным, чем возможное предельное ускорение.

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

Есть несколько причин, по которым он не работает должным образом.

  • Процессор может идеально предсказывать небольшие циклы (n <64).
  • Процессор может идеально предсказывать небольшие повторяющиеся шаблоны (n ~ 7).
  • Сам процессор может оценить вероятность перехода во время выполнения лучше, чем компилятор / программист во время компиляции.
  • предсказуемость (= вероятность, что ветвь будет предсказана правильно) ветки равна гораздо важнее, чем вероятность того, что ветвь будет взята. К сожалению, это сильно зависит от архитектуры, и предсказать предсказуемость ветвления, как известно, сложно.

Подробнее о внутренних работах по предсказанию ветвлений читайте в руководствах Agner Fogs . См. Также список рассылки gcc .

71
ответ дан 24 November 2019 в 12:17
поделиться

Pentium 4 (также известный как микроархитектура Netburst) имел подсказки предиктора ветвления в качестве префиксов к инструкциям jcc, но только P4 когда-либо что-либо делал с ними. См. http://ref.x86asm.net/geek32.html . А также Раздел 3.5 превосходного руководства по asm opt от Agner Fog , из http://www.agner.org/optimize/ . У него также есть руководство по оптимизации в C ++.

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

Официально опубликовано немного о том, как именно предсказатели ветвлений и целевые буферы ветвлений в самые последние процессоры Intel и AMD ведут себя. Руководства по оптимизации (легко найти на AMD и Intel) s веб-сайты) дают несколько советов, но не документируют конкретное поведение. Некоторые люди запускали тесты, чтобы попытаться угадать реализацию, например, сколько записей BTB имеет Core2 ... В любом случае, идея явного указания предиктора была оставлена ​​(на данный момент).

Документировано, например, что Core2 имеет буфер истории переходов, который позволяет избежать неверного прогнозирования выхода из цикла, если цикл всегда выполняет постоянное короткое количество итераций, <8 или 16 IIRC. Но не спешите разворачиваться, потому что цикл, который умещается в 64 байта (или 19uops на Penryn), не будет иметь узких мест при извлечении инструкций, потому что он воспроизводится из буфера ... прочтите pdf-файлы Агнера Фога, они отлично .

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


Эффект ] Вероятно, / 1152513]. (Это могло бы быть сделано с gcc -march = pentium4 , но не при компиляции для чего-либо еще).

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

См. В чем преимущество GCC __builtin_expect в операторах if else? для конкретного примера code-gen.

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

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


Оптимизация на основе профиля GCC обычно делает вероятные / маловероятные макросы ненужными. Компилятор собирает данные времени выполнения о том, каким путем каждая ветвь пошла для решений по компоновке кода, и для определения горячих и холодных блоков / функций. (например, он будет разворачивать циклы в горячих функциях, но не в холодных.) См. -fprofile-generate и -fprofile-use в руководстве GCC . Как использовать оптимизацию на основе профиля в g ++?

В противном случае GCC должен будет угадывать, используя различные эвристики, если вы не использовали вероятные / маловероятные макросы и не использовали PGO. -fguess-ветвь-вероятность включена по умолчанию на -O1 и выше.

https://www.phoronix.com/scan.php?page=article&item=gcc -82-pgo & num = 1 содержит результаты тестов PGO по сравнению с обычным тестом с gcc8.2 на процессоре масштабируемого сервера Xeon. (Skylake-AVX512). Каждый тест получил хотя бы небольшое ускорение, а некоторые выиграли примерно на 10%. (Большая часть этого, вероятно, связана с развертыванием цикла в горячих циклах, но часть этого предположительно связана с улучшенной компоновкой веток и другими эффектами.)

-fguess-ветвь-вероятность включена по умолчанию на -O1 и выше.

https://www.phoronix.com/scan.php?page=article&item=gcc -82-pgo & num = 1 содержит результаты тестов PGO по сравнению с обычным тестом с gcc8.2 на процессоре масштабируемого сервера Xeon. (Skylake-AVX512). Каждый тест получил хотя бы небольшое ускорение, а некоторые улучшились примерно на 10%. (Большая часть этого, вероятно, связана с развертыванием цикла в горячих циклах, но часть этого предположительно связана с улучшенной компоновкой веток и другими эффектами.)

-fguess-ветвь-вероятность включена по умолчанию на -O1 и выше.

https://www.phoronix.com/scan.php?page=article&item=gcc -82-pgo & num = 1 содержит результаты тестов PGO по сравнению с обычным тестом с gcc8.2 на процессоре масштабируемого сервера Xeon. (Skylake-AVX512). Каждый тест получил хотя бы небольшое ускорение, а некоторые выиграли примерно на 10%. (Большая часть этого, вероятно, связана с развертыванием цикла в горячих циклах, но часть этого предположительно связана с улучшенной компоновкой веток и другими эффектами.)

31
ответ дан 24 November 2019 в 12:17
поделиться

Для меня это звучит излишне - такой тип оптимизации сэкономит крошечное количество времени. Например, использование более современной версии gcc будет иметь гораздо большее влияние на оптимизацию. Также попробуйте включить и отключить все различные флаги оптимизации; не все они улучшают производительность.

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

EDIT: спасибо за комментарии. Я создал эту вики-страницу сообщества, но оставил ее, чтобы другие могли видеть комментарии.

-9
ответ дан 24 November 2019 в 12:17
поделиться

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

Также обязательный комментарий о преждевременной оптимизации и о том, как это плохо.

РЕДАКТИРОВАТЬ: Дракоша упомянул некоторые макросы для GCC. Однако я считаю, что это оптимизация кода и на самом деле не имеет ничего общего с предсказанием ветвлений.

-9
ответ дан 24 November 2019 в 12:17
поделиться

В SUN C Studio для этого случая определены некоторые прагмы.

#pragma редко_called ()

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

Но нет способа пометить общий оператор if / while

1
ответ дан 24 November 2019 в 12:17
поделиться

Я предлагаю скорее чем беспокоиться о предсказании ветвлений, профилируйте код и оптимизируйте его, чтобы уменьшить количество ветвей. Один пример - это развертывание цикла, а другой - использование методов логического программирования вместо использования операторов if .

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

Я оптимизировал программу с 1 часа выполнения до 2 минут, используя развертывание цикла и большие буферы ввода-вывода. В этом случае прогнозирование ветвлений не принесло бы большой экономии времени.

6
ответ дан 24 November 2019 в 12:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: