Пространственная и временная локальность
Я понимаю определения терминов, но у меня возникли проблемы с применением их понятий к коду. Для упражнения нас просят описать, является ли следующий код пространственным или временным:
for (int i=0; i<10; i++) {
printf(some_array[i]);
}
Я чувствую, что это пространственная локальность, потому что при доступе к одному индексу массива будет доступна следующая ячейка памяти индекса, как только цикл повторится. Правильно ли на это смотреть? Что определяет, является ли код временным или пространственным? Еще много примеров было бы здорово.
4 ответов
Это немного глупое занятие, на самом деле. Код не является временным или пространственным.
но временная локальность подразумевает, что вы собираетесь получить доступ к одному и тому же адресу несколько раз, относительно близко во времени. Вы не делаете этого здесь (Если вы не считаете доступ i
, Я думаю), поэтому в процессе исключения вы можете заключить, что это должна быть пространственная локальность.
точнее, вы получаете доступ some_array[0]
, потом some_array[1]
, etc. так далее. Они близко друг к другу в адресное пространство, так что да, это может быть "полагаться" на пространственное город.
в контексте аппаратной кэш-памяти, где эти понятия обычно возникают, анализ обычно не выполняется на основе адреса памяти, так сказать. Локальность анализируется по доступу к блокам памяти, которые передаются между кэшем и основной памятью.
Если ты думаешь об этом таким образом, ваш код имеет как временную, так и пространственную локализацию. Когда ваш код читает some_array[0]
, если его адрес не найден в кэше, он считывается из основной памяти и всего блока который содержит его, копируется в кэш. Он заменяет некоторый другой блок после определенной политики: MRU, например.
затем, когда вы получаете доступ some_array[1]
спустя короткое время, его блок уже находится в кэше, поэтому времени будет меньше. Обратите внимание, что вы получили доступ к тому же Блоку, и в течение небольшого количества времени. Таким образом, у вас есть как пространственная, так и временная локальность.
кэш-память использует пространственную и временную локальность для обеспечения более быстрого доступа к памяти. С другой стороны, может ли ваш код воспользоваться этим-это совершенно другая проблема. Тем не менее, компилятор сделает большинство оптимизаций для вас, поэтому вы должны беспокоиться об этом только после нахождения узкого места в сеансе профиля. В средах Linux, модулем cachegrind идеально подходит для этого.
этот код имеет временную локальность в кэше инструкций, потому что вы повторяете код с каждым циклом (предполагая, что ваш оптимизатор не развернул цикл). Он также имеет пространственную локальность в кэше данных, потому что если вы получаете доступ к элементу массива i, вы скоро получите доступ к элементам i+1, i+2 и т. д. Если размер строки кэша данных равен 16 байтам, а массив-32-разрядным целым числам, то кэш данных также загружает элементы 1, 2 и 3, Когда вы запрашиваете элемент 0 (при условии, что наш массив запущен в кэше линия границы).
код имеет только пространственную локальность, но не временную локальность-в контексте доступа к кэш-памяти.
при загрузке данных в кэш загружается целая строка / блок-следовательно, последующие обращения к точно такому же местоположению памяти, а также адреса, которые также являются частью того же блока в кэше, будут иметь быстрое время доступа.
есть способы оптимизировать ваш код таким образом, чтобы как можно больше чтения из кэша, а не непосредственно из main память: 1. Если вы можете получить доступ ко всем близлежащим адресам памяти, просто воспользовавшись первым пропуском кэша, и прежде чем этот блок будет вытеснен из кэша, вы используете пространственную локальность. 2. Если вы обращаетесь к одному и тому же местоположению памяти столько раз, сколько требуется вашей программой, прежде чем блок в кэше будет вытеснен - тогда вы пользуетесь временной локальностью.
примеры, такие как умножение матрицы, будут иметь как временную, так и пространственную локальность.