Каждый адрес памяти «сопоставляется» с собственным кешем, установленным в кеше (ах) ЦПУ, на основе операции по модулю адреса.
Есть ли способ доступа к двум массивам одинакового размера, например так:
int* array1; //How does the alignment affect the possibility of cache collisions?
int* array2;
for(int i=0; i<array1.size(); i++){
x = array1[i] * array2[i]; //Can these ever not be loaded in cache at same time?
}
может вызвать снижение производительности, потому что элементы в массивах array1 [i] и array2 [i] дают один и тот же результат строки кэша по модулю? Или это действительно увеличит производительность, потому что для получения двух местоположений данных потребуется загрузить только одну строку кэша?
Сможет ли кто-нибудь привести пример вышеизложенного, показывающий изменения производительности из-за отображений кэша, включая то, как на это может повлиять выравнивание массивов?
(Причиной моего вопроса является то, что я пытаюсь понять, когда возникает проблема производительности из-за выравнивания данных / сопоставления адресов с одной и той же строкой кэша, что приводит к тому, что один из фрагментов данных не сохраняется в кэше)
NB. Возможно, я перепутал кэш терминов «строка» и «набор» — пожалуйста, не стесняйтесь исправлять.
Прямо сейчас ваш код не имеет особого смысла, так как вы не выделяли память для массивов. Указатели — это всего лишь две неинициализированные переменные, стоящие в стеке и указывающие ни на что. Кроме того, указатель на int * на самом деле не имеет size()
функция.
Предполагая, что вы исправите все это, если вы делаете выделение, вы можете решить, следует ли размещать данные непрерывно или нет. Вы можете выделить 2 * N целых чисел для одного указателя, а другой указывать на середину этого региона.
Основное соображение здесь заключается в следующем: если массивы достаточно малы, чтобы не охватывать желаемый уровень кэша, их сопоставление будет непрерывным, чтобы избежать необходимости использовать одни и те же наборы кэша между ними. Это может улучшить производительность, поскольку одновременный доступ к одним и тем же наборам часто неоптимален из-за соображений HW.
Поразительное рассмотрение (будут ли два массива выбрасывать строки друг друга из кэша) на самом деле не является проблемой, так как большинство кэшей сегодня имеют некоторый уровень ассоциативности — это означает, что массивы могут отображаться на одни и те же наборы, но жить по-разному , Если массивы слишком велики и превышают общее количество путей вместе, то это означает, что их диапазон адресов несколько раз оборачивается вокруг сопоставления набора кеша, и в этом случае не имеет значения, как он выровнен, вы все равно столкнетесь с некоторыми строками другого массива
например, если у вас в кэше было 4 набора и 2 пути, и вы пытаетесь отобразить 2 массива по 64 дюйма со смещением выравнивания, вы все равно заполните весь кэш —
way0 way1
set 0 array1[0] array2[32]
set 1 array1[16] array2[48]
set 2 array1[32] array2[0]
set 3 array1[48] array2[16]
но, как уже упоминалось выше, доступ в пределах одной итерации будет осуществляться в разных наборах, что может иметь некоторое преимущество.