Недавно Херб Саттер выступил с речью «Современный C ++: что нужно знать». Основной темой этого доклада была эффективность и то, как локальность данных и доступ к памяти имеют значение.
Он также объяснил, как процессор будет любить линейный доступ к памяти (массив / вектор). Он взял один пример из другой классической ссылки «Игровое выступление Боба Нистрома» по теме.
Прочитав эти статьи, я понял, что существует два типа кеша, которые влияют на производительность программы:
похожем на Cachegrind Инструмент также измеряет информацию об инструментах типа кэша нашей программы. Первые пункты были объяснены многими статьями / блогами и о том, как добиться хорошей эффективности кэширования данных (локальность данных).
Однако я не получил много информации по теме Кэш инструкции и о каких вещах мы должны позаботиться в нашей программе, чтобы добиться лучшей производительности? Насколько я понимаю, мы (программист) не имеем большого контроля над тем, какая инструкция или какой порядок будет выполняться.
Было бы неплохо, если бы небольшие программы на c ++ объясняли, как этот счетчик (.i.e кеш инструкций) будет меняться в зависимости от нашего стиля написания программ. Каким лучшим практикам следует следовать, чтобы достичь лучшей производительности в этом направлении?
Я имею в виду, что мы можем понять темы кеширования данных, если наша программа (вектор против списка) аналогичным образом позволяет объяснить, что касается 2-го пункта. Основная цель этого вопроса — как можно лучше понять эту тему.
Любой код, который изменяет поток выполнения, влияет на кэш инструкций. Это включает вызовы функций и циклы, а также разыменование указателей на функции.
Когда выполняется команда перехода или перехода, процессор должен потратить дополнительное время, решая, находится ли код в кэше команд или ему необходимо перезагрузить кэш команд (из места назначения ветви).
Например, некоторые процессоры могут иметь достаточно большой кэш команд для хранения кода выполнения для маленьких циклов. Некоторые процессоры не имеют большого кеша команд и просто перезагружают его. Перезагрузка кэша команд занимает время, которое может быть потрачено на выполнение инструкций.
Поиск по этим темам:
Редактировать 1: методы программирования для повышения производительности
Для повышения производительности и уменьшения перезагрузки кэша команд выполните следующие действия:
Сократить «если» заявления
Создайте свой код, чтобы минимизировать операторы if. Это может включать булеву алгебру, использование математики или упрощение сравнений (действительно ли они нужны?). Предпочитаю уменьшать содержание предложений «then» и «else», чтобы компилятор мог использовать инструкции языка условного ассемблера.
Определите маленькие функции как встроенные или макросы
С вызовом функций связаны накладные расходы, такие как сохранение местоположения возврата и перезагрузка кэша команд. Для функций с небольшим количеством операторов попробуйте предложить компилятору сделать их встроенными. Встраивание означает вставку содержимого кода, где выполняется, а не вызов функции. Поскольку избегается вызов функции, возникает необходимость перезагрузить кэш команд.
Развернуть петли
Для небольших итераций не зацикливайтесь, а повторяйте содержимое цикла (некоторые компиляторы могут делать это при более высоких настройках уровня оптимизации). Чем больше контента повторяется, тем меньше количество веток к началу цикла и тем меньше нужно перезагрузить кэш команд.
Используйте поиск в таблице, а не операторы «если»
Некоторые программы используют лестницы «если-еще-если» для отображения данных на значения. Каждый оператор «if» является перерывом в выполнении в кэше команд. Иногда, с небольшой математикой, значения могут быть помещены в таблицу как массив, и индекс вычисляется математически. Как только индекс известен, процессор может извлечь данные, не нарушая кеш инструкций.
Изменить данные или структуры данных
Если тип данных является постоянным, программа может быть оптимизирована вокруг данных. Например, программа, обрабатывающая пакеты сообщений, может основывать свои операции на основе идентификаторов пакетов (например, массивов указателей на функции). Функции будут оптимизированы для обработки пакетов.
Измените связанные списки на массивы или другой контейнер с произвольным доступом. К элементам массива можно обращаться с помощью математики, а не выполнения прерываний. Связанные списки должны быть просмотрены (цикл), чтобы найти элемент.
Других решений пока нет …