#c #caching
#c #кэширование
Вопрос:
У меня есть кэш черного ящика, и мне нужно найти ассоциативность и размер блока, написав программу на C.
Я запускаю свою программу на gcc и пытаюсь узнать ассоциативность для системного кэша. В моей программе я создал огромный массив и пытаюсь прочитать все элементы массива, что дает мне размер кэша.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void main()
{
int array_1[250000], array_2[1000000], array_element;
int i, j, n;
clock_t start_1, end_1, start_2, end_2;
float cpu_time_used, avg_time_per_elem;
/* Fill the array with data */
for(i=0;i<250000;i )
array_1[i] = 123;
for(i=0;i<500000;i )
array_2[i] = 123;
/* To check data integrity */
printf("First Array element = %d n", array_1[0]);
printf("Middle Array element = %d n", array_1[124999]);
printf("Last Array element = %d n", array_1[249999]);
/* Start measuring the clock cycles */
start_1 = clock();
printf("n start = %dn", start_1);
for(i=0; i<1000;i ) //number of iterations
{
for(j=0; j<250000; j ) //number of elements
{
array_element = array_1[j];
}
}
end_1 = clock();
printf(" end = %dn n", end_1);
cpu_time_used = end_1 - start_1;
printf("CPU time used = %.10f ms n", cpu_time_used);
cpu_time_used = cpu_time_used/CLOCKS_PER_SEC;
printf("t = %.6f seconds n", cpu_time_used);
/* Calculating the average latency to access the data in cache */
avg_time_per_elem = cpu_time_used/(i*j);
printf("Average time to access one element = %.15f seconds = %.6f nanoseconds n n n", avg_time_per_elem, (avg_time_per_elem*1000000000));
start_2 = clock();
printf("n start = %dn", start_2);
for(i=0; i<2000;i ) //number of iterations
{
for(j=0; j<1000000; j ) //number of elements
{
array_element = array_2[j];
}
}
end_2 = clock();
printf(" end = %dn n", end_2);
cpu_time_used = end_2 - start_2;
printf("CPU time used = %.10f ms n", cpu_time_used);
cpu_time_used = cpu_time_used/CLOCKS_PER_SEC;
printf("t = %.6f seconds n", cpu_time_used);
/* Calculating the average latency to access the data in cache */
avg_time_per_elem = cpu_time_used/(i*j);
printf("Average time to access one element = %.15f seconds = %.6f nanoseconds n", avg_time_per_elem, (avg_time_per_elem*1000000000));
}
Таким образом, увеличивая размер массива при каждом запуске, я могу вычислить размер кэша L1 равным 32 КБ, т.е. в момент, когда время доступа резко возрастает. Но не могу понять, как найти ассоциативность и размер блока.
Комментарии:
1. В первой версии вопроса я думал, что это академическое упражнение, в котором «кэш черного ящика» каким-то образом отделен от собственного кэша процессора. Характеристика собственного кэша процессора кажется невыполнимой задачей.
2. Это действительно академическая задача. Я смог охарактеризовать время попадания и время пропуска кэша L1. Я искал онлайн-ресурсы, но все еще не могу найти возможный способ найти ассоциативность. Из команды>cpuid я вижу, что размер кэша для L1 равен 32 K. Но мне нужно проверить это с помощью моей программы.
3. При заданном ассоциативном кэше адреса, разделенные размером кэша (32 КБ), должны использовать один и тот же набор в кэше. Если кэш имеет двустороннюю ассоциативную привязку, то два адреса (например, 0x1000000 и 0x1008000) должны иметь хорошую производительность, но три адреса (0x1000000, 0x1008000, 0x1010000) не будут. Если кэш является 4-сторонним, то вам потребуется пять адресов, прежде чем производительность снизится, и так далее.
4. Однако проблема заключается в выборе адресов, которые в противном случае не используются. Например, если переменная
i
случайно использует тот же набор, что и два адреса, которые вы тестируете, то вы получите ужасную производительность в двустороннем кэше.5. у @user3386109 есть ответ. Чтобы выбрать подходящую область, вам нужно взять адрес переменной стека, чтобы узнать, где находится ваш стек (поместите ваши рабочие переменные в структуру, чтобы вы знали выравнивание), а также адрес текущей функции. Затем либо выберите тот, который совпадает или не совпадает с вашими рабочими данными / кодом.