Статические переменные препятствуют кешированию данных? - PullRequest
0 голосов
/ 18 февраля 2019

С Оптимизация программного обеспечения на C ++ (Раздел 7.1) ,

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

Использование static в этом случае исключает применение к C и C ++ в точном случае статической длительности хранения.

Может ли кто-нибудь пролить свет на то, почему (или ли) кэширование данных менее эффективно для статических переменных продолжительности?Вот конкретное сравнение:

void foo() {
  static int static_arr[] = {/**/};
}
void bar() {
  int local_arr[] = {/**/};
}

Я не вижу причин, по которым статические данные кэшируются иначе, чем любые другие виды данных.В данном примере я думаю, что foo будет быстрее, поскольку стеку исполнения не нужно загружать static_arr, тогда как в bar стеку исполнения нужно загружать local_arr.В любом случае, если эти функции были вызваны неоднократно, и static_arr, и local_arr будут кэшированы.Я не прав?

Ответы [ 3 ]

0 голосов
/ 18 февраля 2019

Это утверждение имеет или не имеет смысла в зависимости от того, как вы его акцентируете:

Чтение 1:

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

Все вышеперечисленное делает кеширование данных менее эффективным.

Это нонсенс.

Чтение 2:

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

Недостатком является то, что пространство памяти занимает все время выполнения программы ...

... даже если переменная используется только в небольшой части программы.В одном случае это может сделать кэширование данных менее эффективным.

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

В конкретном случаеЕсли вы продемонстрируете, ответ будет «это зависит».

Да, инициализация static_arr является одноразовой операцией, поэтому ее можно рассматривать как бесплатную.

Да, инициализация local_arr происходит каждый раз, когда функциявызывается, но может быть так:

  1. эта инициализация тривиальна, или
  2. инициализация пропускается компилятором как часть прохода оптимизатора

В общем, если вы не имеете в виду конкретную оптимизацию, лучше (tm) написать код, в котором явно указано желаемое поведение , то есть:

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

  • использовать локальные переменные (строго, переменные с автоматическимдлительность хранения), когда существующие значения не имеют смысла при входе или выходе из функции.

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

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

В этом случае фактическим состоянием переменной является размер выделенного буфера.,Таким образом, состояние важно при входе и выходе функции, например:

  std::string const& to_string(json const& json_object)
  {
    static thread_local buffer;               // thread-safe, auto-expanding buffer storage
    buffer.clear();                           // does not release memory
    serialise_to_string(buffer, json_object); // may allocate memory occasionally
    return buffer;
  }
0 голосов
/ 18 февраля 2019

Ответ от rustyx объясняет это.Локальные переменные хранятся в стеке.Пространство стека освобождается при возврате функции и используется повторно при вызове следующей функции.Кэширование более эффективно для локальных переменных, потому что одно и то же пространство памяти используется снова и снова, в то время как статические переменные разбросаны по разным адресам памяти, которые никогда не могут быть повторно использованы для других целей.Хранятся ли статические данные в разделе DATA (инициализировано) или в разделе BSS (не инициализировано), в этом отношении не имеет значения.Пространство вершины стека, скорее всего, останется в кэше в течение всего выполнения программы и будет многократно использоваться.

Другое преимущество состоит в том, что ограниченное число локальных переменных может быть доступно с 8-битным смещением относительно стека.указатель, в то время как статическим переменным требуется 32-разрядный абсолютный адрес (в 32-разрядной версии x86) или 32-разрядный относительный адрес (в x86-64).Другими словами, локальные переменные могут сделать код более компактным и улучшить использование кеша кода, а также кеша данных.

// Example
int main () {
  f();
  g();
  return 0;
}

void f() {
   int x; 
   ...
}

void g() {
   int y;  // y may occupy the same memory address as x
   ...
}
0 голосов
/ 18 февраля 2019

В общем, Агнер Фог обычно знает, о чем говорит.

Если мы прочитаем цитату в контексте раздела 7.1 Различные типы хранилищ переменных , мы увидим, что он имеет в видупо " менее эффективному кешированию " в начале раздела:

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...