Как написать программу на C для измерения скорости кэширования?

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

Если вы можете это сделать, то как измерить скорость каждого уровня кэша?

3 ответов


это обычно требует некоторого знания "геометрии" кэша и других его аспектов. Также полезно иметь некоторый контроль над системой за пределами простого доступа пользователя к ней и зависимых от реализации вещей, таких как более точное время, чем может быть предоставлено через стандартный C clock механизм.

вот первоначальный подход:

  • напишите процедуру, которая принимает указатель на память, длину и количество повторений и считывает всю эту память в последовательном порядке, неоднократно.
  • напишите процедуру, которая берет указатель на память, длину и количество повторений и записывает во всю эту память в последовательном порядке, неоднократно.
  • вышеуказанные процедуры, возможно, придется преобразовать свои указатели в volatile чтобы предотвратить оптимизацию компилятором доступа, которые в противном случае не имеют никакого эффекта.
  • выделить большой объем памяти.
  • вызовите каждую из вышеуказанных процедур, получая текущее время до и после каждого вызова и вызова с различными длинами, чтобы увидеть время для разных длин.

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

вот некоторые причины, по которым подход неадекватен:

  • он не контролирует инструкции, используемые для чтения и записи кэша. Компилятор C вполне может генерировать инструкции load-word и store-word, но многие современные процессоры имеют инструкции, которые могут загружать и хранить 16 байтов за раз, и чтение и запись могут быть быстрее с этими инструкциями, чем с четырехбайтовыми инструкциями word.
  • кэш будет вести себя по-разному при доступе в последовательно, чем при случайном доступе. Большинство кэшей пытаются отслеживать, когда используются данные, так что недавно использованные данные хранятся в кэше, в то время как другие данные выбрасываются. Части доступа реальных программ обычно отличаются от последовательных операций, описанных выше.
  • в частности, последовательные записи в память могут заполнить всю строку кэша, так что ничего не нужно читать из памяти, в то время как шаблон реального использования, который записывает только одно слово в конкретное местоположение может быть реализовано путем чтения строки кэша из памяти и слияния в измененных байтах.
  • конкуренция с другими процессами в вашей системе будет мешать тому, что находится в кэше и с измерением.

вам нужно придумать эвристику, которая заставляет 100% (или очень близко) пропускать кэш (надеюсь, у вас есть код недействительности кэша?) и 100% попадание в кэш. Ура, это работает для 1 уровня кэша. Теперь, как сделать то же самое для уровня 2 и 3?

со всей серьезностью, вероятно, нет способа сделать это 100% надежно без специального оборудования и следов, подключенных к процессору и памяти, но вот что я бы сделал:

напишите "кучу" вещей в 1 место в память-достаточно, чтобы вы могли быть уверены, что он последовательно попадает в кэш L1 и записывает время (что влияет на ваш кэш, поэтому будьте осторожны). Вы должны сделать этот набор записей без ветвей, чтобы попытаться избавиться от несоответствий прогнозирования ветвей. Это лучшее время. Теперь время от времени записывайте данные кэш-строки в случайное удаленное место в ОЗУ в конце вашего известного местоположения и записывайте Новое время. Надеюсь, это займет больше времени. Продолжайте записывать различные раз и, надеюсь, вы увидите пару таймингов, которые, как правило, группируются. Каждая из этих групп "может" показывать тайминги для L2, L3 и тайминги доступа к памяти. Проблема в том, что есть так много других вещей, которые мешают. ОС может контекстно переключить вас и испортить ваш кэш. Прерывание может прийти и через ваше время. Будет много вещей,которые могут сбросить ценности. Но, надеюсь, вы получите достаточно сигнала в своих данных, чтобы увидеть, работает ли он.

этот вероятно, было бы проще сделать на более простой, встроенной системе типов, где ОС (если таковая имеется) не будет мешать вам.


посмотри cachegrind-valgrind:

Cachegrind имитирует, как ваша программа взаимодействует с кэшем машины иерархия и (необязательно) предиктор ветвей. Он имитирует машину с независимыми инструкциями первого уровня и кэшами данных (I1 и D1), поддерживается единым кэшем второго уровня (L2). Это точно соответствует конфигурация многих современных машин.

см. эти хорошие вопросы, они как-то по теме:

  1. как программно отключить предварительную выборку оборудования?
  2. как бы вы вообще обнаружили ассоциативность строки кэша из кода пользовательского режима?
  3. как аннулировать кэш при бенчмаркинге?