Похоже, что общая логика использования предварительной выборки заключается в том, что предварительная выборка может быть добавлена при условии, что код занят обработкой, пока инструкция предварительной выборки не завершит свою работу. Но похоже, что использование слишком большого количества инструкций предварительной выборки может повлиять на производительность системы. Я считаю, что нам сначала нужно получить рабочий код без инструкции предварительной выборки. Позже нам понадобится различная комбинация инструкций предварительной выборки в различных участках кода и провести анализ, чтобы определить участки кода, которые могут действительно улучшиться благодаря предварительной выборке. Есть ли лучший способ определить точные места, в которых следует использовать инструкцию предварительной выборки?
Инструкция предварительной выборки
Ответы (3)
В большинстве случаев инструкции предварительной выборки приносят мало пользы или не приносят никакой пользы, а в некоторых случаях даже могут быть контрпродуктивными. Большинство современных процессоров имеют механизм автоматической предварительной выборки, который работает достаточно хорошо, поэтому добавление программных подсказок предварительной выборки мало что дает или даже мешает автоматической предварительной выборке и может фактически снизить производительность.
В некоторых редких случаях, например, при потоковой передаче больших блоков данных, для которых вы выполняете очень мало фактической обработки, вам может удастся скрыть некоторую задержку с помощью программно инициируемой предварительной выборки, но это очень сложно сделать правильно - вам нужно запустите предварительную выборку за несколько сотен циклов, прежде чем вы собираетесь использовать данные - сделайте это слишком поздно, и вы все равно получите промах кеша, сделайте это слишком рано, и ваши данные могут быть вытеснены из кеша, прежде чем вы будете готовы их использовать. Часто при этом упреждающая выборка помещается в какую-то несвязанную часть кода, что плохо сказывается на модульности и поддержке программного обеспечения. Что еще хуже, если ваша архитектура изменится (новый процессор, другая тактовая частота и т. Д.), Так что задержка доступа к DRAM увеличивается или уменьшается, вам может потребоваться переместить инструкции предварительной выборки в другую часть кода, чтобы они оставались эффективными.
В любом случае, если вы чувствуете, что действительно должны использовать предварительную выборку, я рекомендую #ifdefs вокруг любых инструкций предварительной выборки, чтобы вы могли скомпилировать свой код с предварительной выборкой и без нее и посмотреть, действительно ли это помогает (или мешает) производительности, например
#ifdef USE_PREFETCH
// prefetch instruction(s)
#endif
В целом, я бы рекомендовал оставить предварительную выборку программного обеспечения на потом в качестве последнего средства микрооптимизации после того, как вы проделали все более продуктивные и очевидные вещи.
Чтобы даже подумать о производительности кода предварительной выборки, уже должно быть проблемой.
1: используйте профилировщик кода. Попытка использовать предварительную выборку без профилировщика - пустая трата времени.
2: всякий раз, когда вы обнаруживаете аномально медленную инструкцию в критическом месте, у вас есть кандидат на предварительную выборку. Часто реальная проблема связана с доступом к памяти в строке перед медленной, а не с медленной, как указывает профилировщик. Выясните, какой доступ к памяти вызывает проблему (не всегда просто), и выполните предварительную загрузку.
3 Снова запустите свой профилировщик и посмотрите, не изменилось ли это. Если бы не вынул. Иногда я таким образом увеличивал скорость петель более чем на 300%. Обычно это наиболее эффективно, если у вас есть цикл с непоследовательным доступом к памяти.
Я полностью не согласен с тем, что он менее полезен на современных процессорах, я обнаружил совершенно противоположное, хотя для более старых процессоров предварительная выборка около 100 инструкций была оптимальной, в наши дни я бы поставил это число примерно на 500.
Конечно, вам нужно немного поэкспериментировать, но это не значит, что вам нужно получить несколько циклов (100–300), прежде чем данные потребуются. Кэш L2 достаточно большой, чтобы предварительно загруженные данные могли оставаться там некоторое время.
Эта предварительная выборка очень эффективна перед циклом (конечно, несколько циклов), особенно если это внутренний цикл, и цикл запускается тысячи и более раз в секунду.
Также для быстрой реализации LL или реализации дерева предварительная выборка может получить ощутимое преимущество, потому что ЦП не знает, что данные потребуются в ближайшее время.
Но помните, что инструкция предварительной выборки потребляет некоторую пропускную способность декодера / очереди, поэтому чрезмерное их использование снижает производительность по этой причине.