Подтвердить что ты не робот

Как найти размер размера строки кеша L1 с измерениями времени ввода-вывода?

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

В неполной попытке выполнить другую часть задания, чтобы найти уровни и размер кеша, у меня есть:

for (i = 0; i < steps; i++) {
    arr[(i * 4) & lengthMod]++;
}

Я думал, может быть, мне просто нужно изменить строку 2, (i * 4) часть? Поэтому, если я превышу размер строки кеша, возможно, мне придется его заменить, что происходит когда-то? Но так ли это так просто? Требуемый блок уже может быть где-то в памяти? Или перпах я все еще могу рассчитывать на то, что, если у меня будет достаточно большой steps, он все равно будет работать довольно точно?

UPDATE

Вот попытка GitHub... главная часть ниже

// repeatedly access/modify data, varying the STRIDE
for (int s = 4; s <= MAX_STRIDE/sizeof(int); s*=2) {
    start = wall_clock_time();
    for (unsigned int k = 0; k < REPS; k++) {
        data[(k * s) & lengthMod]++;
    }
    end = wall_clock_time();
    timeTaken = ((float)(end - start))/1000000000;
    printf("%d, %1.2f \n", s * sizeof(int), timeTaken);
}

Проблема заключается в том, что не существует различий между сроками. FYI. так как он для кеша L1. У меня SIZE = 32 К (размер массива)

4b9b3361

Ответ 1

Выделите массив BIG char (убедитесь, что он слишком велик для установки в кеш L1 или L2). Заполните его случайными данными.

Начните ходить по массиву с шагом n. Сделайте что-то с извлеченными байтами, например, суммируя их.

Оцените и вычислите, сколько байтов в секунду вы можете обрабатывать с разными значениями n, начиная с 1 и считая до 1000 или около того. Убедитесь, что ваш тест распечатывает рассчитанную сумму, поэтому компилятор не может оптимизировать сравниваемый код.

Когда n == ваш размер строки кеша, каждый доступ потребует прочтения новой строки в кеше L1. Таким образом, результаты тестов должны резко снижаться в этот момент.

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

Ответ 2

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

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

     

В принципе, пропуски промахов кэша определяются размером массива. Размеры массива, которые вписываются в   кеш L1 не генерирует пропусков кэша после загрузки данных в кеш. Аналогично,   массивы, которые превышают размер кеша L1, но по-прежнему вписываются в L2, будут вызывать промахи L1, но не пропустить L2. В заключение,   массивы, большие, чем L2, вызывают пропуски L1 и L2.

     

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

     

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

     

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

Мне пришлось прокомментировать #include "math.h", чтобы скомпилировать его, после чего он правильно нашел значения кэша для ноутбука. Я также не мог просматривать созданные файлы postscript.

Ответ 3

Посмотрите, как реализована memtest86. Они каким-то образом измеряют и анализируют скорость передачи данных. Точка изменения скорости соответствует размеру L1, L2 и возможному размеру кеша L3.

Ответ 4

Я думаю, вы должны написать программу, которая будет проходить через массив в случайном порядке, а не прямо, потому что современный процесс делает предварительную выборку оборудования. Например, make array of int, значения которого будут содержать число следующей ячейки. Я сделал аналогичную программу 1 год назад http://pastebin.com/9mFScs9Z Извините за мой engish, я не носитель языка.

Ответ 5

Если вы застряли в грязи и не можете выбраться, посмотрите здесь.

Есть инструкции и код, которые объясняют, как делать то, что вы просите. Код довольно высокого качества. Посмотрите на "Библиотека подпрограмм".

Код и руководства основаны на процессорах X86.

Ответ 6

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

Для микропроцессоров Intel размер Cache Line Size может быть рассчитан путем умножения bh на 8 после вызова функции cpuid 0x1.

Для микропроцессоров AMD размер кеша данных находится в cl, а размер строки кэша команд - в dl после вызова функции cpuid 0x80000005.

Я взял это из этой статьи здесь.

Ответ 7

Я думаю, что достаточно времени для операции, которая использует некоторый объем памяти. Затем прогрессивно увеличивайте память (например, операнды), используемые этой операцией. Когда производительность операции сильно уменьшается, вы нашли предел.

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

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