Как отметить некоторые диапазоны памяти как не кэшируемые с С++? - программирование
Подтвердить что ты не робот

Как отметить некоторые диапазоны памяти как не кэшируемые с С++?

Я читал wikipedia в кэше процессора здесь: http://en.wikipedia.org/wiki/CPU_cache#Replacement_Policies

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

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

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

4b9b3361

Ответ 1

В Windows вы можете использовать VirtualProtect(ptr, length, PAGE_NOCACHE, &oldFlags), чтобы установить поведение кэширования для памяти, чтобы избежать кэширования.

Относительно слишком большого числа указаний: Да, они могут повредить производительность кеша, если вы часто обращаетесь к различным частям памяти (что обычно происходит). Важно отметить, однако, что если вы последовательно разыгрываете один и тот же набор, например, 8 блоков памяти, и только 9-й блок отличается, то это обычно не будет иметь никакого значения, потому что 8 блоков будут кэшироваться после первого доступа.

Ответ 2

Эмпирическое правило для оптимизации доступа к кешу: кластер вместе загружает и сохраняет тот же адрес. Например, следующий код:

for (size_t i=0; i<A.size(); ++i)
  B[i] = func1(A[i]);

for (size_t i=0; i<A.size(); ++i)
  C[i] = func2(A[i]);

Можно оптимизировать доступ к кешу более эффективно:

for (size_t i=0; i<A.size(); ++i) {
  B[i] = func1(A[i]); // A[i] is fetched to the cache
  C[i] = func2(A[i]); // Good chance that A[i] remains in the cache
}

Современные процессоры неплохо предсказывают доступ к памяти с регулярными шаблонами в цикле и могут предварительно кэшировать память для кэширования и ускорить выполнение. Итак, еще одно эмпирическое правило: предпочитает использовать std::vector и std:: array поверх других контейнеров.

Ответ 3

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

Как программист, обычно имеющий дело с платформами x86, отличными от Windows, эта статья о x86 и x86-64 GCC-характеристиках, вероятно, самая полезная.