уменьшение количества кешей благодаря хорошему дизайну - PullRequest
21 голосов
/ 20 января 2009

Как уменьшить количество возможных пропусков кэша при разработке программы на C ++?

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

Ответы [ 6 ]

32 голосов
/ 20 января 2009

Вот некоторые вещи, которые мне нравится учитывать при работе с этим видом кода.

  • Подумайте, хотите ли вы "структуры массивов" или "массивы структур". То, что вы хотите использовать, будет зависеть от каждой части данных.
  • Старайтесь, чтобы структуры были кратны 32 байтам, чтобы они равномерно упаковывали строки кэша.
  • Разделите ваши данные на горячие и холодные элементы. Если у вас есть массив объектов класса o, и вы часто используете ox, oy, oz вместе, но только изредка вам нужен доступ к oi, oj, ok, тогда подумайте о том, чтобы соединить вместе ox, oy и oz и переместить i, j и k частей параллельной подмышечной структуры данных.
  • Если у вас имеются многомерные массивы данных, то с обычными компоновками в порядке строк доступ будет очень быстрым при сканировании по предпочтительному измерению и очень медленным по другим. Сопоставление его с кривой заполнения пространства вместо этого поможет сбалансировать скорости доступа при перемещении в любом измерении. (Методы блокировки похожи - они просто Z-порядка с большим основанием.)
  • Если вам необходимо пропустить кеш, попробуйте как можно больше использовать эти данные, чтобы амортизировать стоимость.
  • Вы делаете что-нибудь многопоточное? Следите за замедлением из-за согласованности протоколов кэша. Флажки пэдов и маленькие счетчики, чтобы они были на отдельных строках кеша.
  • SSE в Intel предоставляет некоторые встроенные функции предварительной выборки, если вы знаете, к чему вы будете обращаться достаточно заблаговременно.
8 голосов
/ 20 января 2009

Есть очень хорошее видео от Херба Саттера, в котором упоминается эта тема

Для операций с данными

  1. использовать массивы и векторы над списками, картами и наборами

  2. обработка по строкам над столбцами

2 голосов
/ 20 января 2009

Также, если вы делаете C ++ и многопоточность, вам необходимо учитывать ложное совместное использование, локальность и актуальность данных в кеше каждого процессора. Это может иметь большое значение. Кроме того, особенно в многопоточном вычислении вещи в режиме LIFO более эффективны, чем вычисления в режиме FIFO, но они также применимы в архитектуре с одним процессором.

2 голосов
/ 20 января 2009

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

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

Немного устарело, но в «Черной книге по программированию» Майка Абраша есть много хороших общих советов.

2 голосов
/ 20 января 2009

Разрешить ЦП эффективно извлекать данные. Например, вы можете уменьшить число пропусков кэша номеров при обработке многомерных массивов по строкам, а не по столбцам, циклам развертывания и т. Д.

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

1 голос
/ 20 января 2009

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

...