Часть 1: Являются ли отдельные распределения смежными?
Ответ , вероятно, не . То, как происходит динамическое распределение, зависит от реализации. Если вы выделяете память, как в приведенном выше примере, два отдельных выделения могут быть смежными, но нет гарантии того, что это произойдет (и на него никогда не следует полагаться, что оно произойдет).
Различные реализации c ++ используют разные алгоритмы для определения того, как распределена память.
Часть 2. Является ли распределение случайным?
Несколько; но не полностью. Память не распределяется намеренно случайным образом. Зачастую распределители памяти пытаются размещать блоки памяти рядом друг с другом, чтобы минимизировать количество сбоев страниц и кеша, но это не всегда возможно сделать.
Распределение происходит в два этапа:
- Распределитель запрашивает большой кусок памяти у ОС
- Берут фрагменты этого большого куска и возвращают их всякий раз, когда вы вызываете new, пока вы не запросите больше памяти, чем нужно, и в этом случае он запросит другой большой кусок из ОС.
На этом втором этапе реализация может предпринять попытки выделить что-то в памяти рядом с другими недавними выделениями, однако она слабо контролирует первый этап (и ОС обычно просто предоставляет всю доступную память без какого-либо знания о других). ассигнования по вашей программе).
Часть 3: как избежать ошибок в кэше
Если ошибки в кеше являются узким местом в вашем коде,
- Постарайтесь уменьшить количество косвенных ссылок (сохраняя объекты в массивах по значению, а не по указателю);
- Убедитесь, что память, с которой вы работаете, является смежной, насколько позволяет дизайн (поэтому используйте std :: array или std :: vector вместо связанного списка и предпочитайте несколько больших выделений множеству маленьких ); и
- Постарайтесь спроектировать алгоритм так, чтобы он как можно меньше перепрыгивал в памяти.
Хороший общий принцип - просто использовать std :: vector объектов, если у вас нет веских причин использовать что-то более причудливое. Поскольку они имеют лучшую локальность кэша, std :: vector быстрее вставляет и удаляет элементы, чем std :: list, даже до десятков или даже сотен элементов.
Наконец: попробуйте воспользоваться стеком. Если нет веской причины для того, чтобы что-то указывало, просто объявите переменную, которая находится в стеке. По возможности
- Предпочитают использовать
MyClass x{};
вместо MyClass* x = new MyClass{};
и
- Предпочитают
std::vector<MyClass>
вместо std::vector<MyClass*>
.
Если вы можете использовать статический полиморфизм (т. Е. Шаблоны), то используйте его вместо динамического полиморфизма.