Я пытаюсь определить время, необходимое для чтения элемента, чтобы убедиться, что это попадание в кеш или промах кеша. чтобы чтение было в порядке, я использую функцию _mm_lfence(). Я получил неожиданные результаты, и после проверки я увидел, что накладные расходы функции lfence не являются детерминированными. Итак, я выполняю программу, которая измеряет эти накладные расходы в цикле, например, из 100 000 итераций. Я получаю результаты более 1000 тактовых циклов за одну итерацию, а в следующий раз - 200. Что может быть причиной такой разницы между накладными расходами функции lfence, и если это настолько ненадежно, как я могу правильно оценить задержку кэш-попаданий и кэш-промахов? Я пытался использовать тот же подход, что и в этом посте: Измерение задержки памяти с помощью счетчика меток времени
код, который дает ненадежные результаты, таков:
for(int i=0; i < arr_size; i++){
_mm_mfence();
_mm_lfence();
t1 = __rdtsc();
_mm_lfence();
_mm_lfence();
t2 = __rdtsc();
_mm_lfence();
arr[i] = t2-t1;
}
значения в arr варьируются в разных диапазонах, arr_size равен 100 000.
Нет, это не так, но я считаю ru_nvcsw и ru_nivcsw, которые сообщают, как часто происходило переключение контекста, равно 4. Нужно ли также проверять прерывания для этого процесса? Или как я могу это сделать?
Если вы ищете другие примеры кода для этого, проверьте github для spectre/meltdown/l1tf PoC, так как измерение времени доступа является необходимым компонентом для них.





I get results of more than 1000 clock cycle for one iteration and next time it's 200.
Похоже, ваш процессор увеличил тактовую частоту от простоя до нормальной тактовой частоты после первых нескольких итераций.
Помните, что RDTSC подсчитывает циклы ссылка (фиксированная частота, равная или близкая к максимальной нетурбо-частоте процессора), не основные такты. (холостой/турбо/любой). В старых процессорах RDTSC подсчитывал тактовые циклы ядра, но уже много лет производители процессоров имеют фиксированную частоту RDTSC, что делает ее полезной для clock_gettime(), и рекламируют этот факт с битом функции invariant_tsc CPUID. См. также Получить количество циклов процессора?
Если вы действительно хотите использовать RDTSC вместо счетчиков производительности, отключите турбо и используйте цикл прогрева, чтобы получить максимальную частоту процессора.
Существуют библиотеки, которые позволяют вам программировать счетчики производительности HW и устанавливать разрешения, чтобы вы могли запускать rdpmc в пользовательском пространстве. Это на самом деле имеет меньшие накладные расходы, чем rdtsc. См. Какой будет точный код для подсчета промахов кеша последнего уровня в архитектуре Intel Kaby Lake? для сводки способов доступа к счетчикам производительности в пользовательском пространстве.
Я также нашел документ о добавлении поддержки rdpmc в пользовательском пространстве в Linux perf (PAPI): ftp://ftp.cs.uoregon.edu/pub/malony/ESPT/Papers/espt-paper-1.pdf. IDK, если он попал в основной код ядра / производительности или нет.
Здравствуйте, я прочитал о RDTSC и думаю, что понял суть этого: «Он работает на номинальной частоте процессора». Таким образом, проблема в том, что он начинает тикать с заявленной частотой, независимой от фактической частоты процессора в данный момент. Тогда это должно означать, что проблема не в функции защиты и она занимает одинаковое время, но время измеряется неправильно.
Ну, честно говоря, у меня нет сильных предпочтений к одному конкретному способу ведения дел, я просто хочу, чтобы результат был правильным :) о «Событиях мониторинга производительности», если я не ошибаюсь, с его помощью я могу, например, прочитать количество загрузок кеша. как я видел по указанной ссылке. Но это число даст мне полное количество для процесса, возможно, не точное количество конкретных промахов и попаданий в кеш, которые меня интересуют. Или я могу настроить его так, чтобы я мог подсчитывать промахи или попадания в кеш для конкретного чтения?
@AnaKhorguani: вы можете поставить rdpmc до и после блока или отдельной инструкции и вычесть. (Вам может понадобиться lfence для предотвращения переупорядочения, я не уверен. Я не думаю, что он сериализуется в потоке инструкций.) И кстати, rdtsc правильно измеряет время. Просто время — это не то, что вам нужно, это основные тактовые циклы. (Поскольку служебные данные измерения lfence + rdtsc представляют собой постоянное количество циклов, а не наносекунд.)
perf определенно поддерживает встречные запросы на основе rdpmc в пользовательском пространстве. Это самый простой способ заставить rdpmc работать в Linux.
Я пытаюсь протестировать библиотеку PAPI, которую, надеюсь, правильно установил. В отдельном файле у меня есть моя программа .c, и я включаю этот заголовок #include <papi.h>. Я думаю, что это не должно быть проблемой, так как я могу определить переменную типа PAPI_event_info_t. Однако, когда я пытаюсь скомпилировать код с оператором: PAPI_library_init, я получаю сообщение об ошибке: (.text+0x41): неопределенная ссылка на `PAPI_library_init'. Я пытаюсь понять, в чем проблема, и много гуглю, но есть ли шанс, что вы могли бы предложить, как я могу скомпилировать программу с функциями библиотеки PAPI?
я должен скомпилировать с дополнительными флагами?
@AnaKhorguani: да, очевидно, вам нужна правильная опция библиотеки -l. Я тоже гуглил, но не нашел, какая библиотека на самом деле содержит функции perf.
Я нашел -lpapi, и после добавления библиотеки в путь это сработало. Я могу скомпилировать и запустить программу с функциями папи, но теперь у меня другая проблема. когда я пытаюсь это сделать: if ((num_hwcntrs = PAPI_num_counters()) <= PAPI_OK) printf("Эта система имеет %d доступных счетчиков. \n", num_hwcntrs); Я понимаю, что в системе 0 доступных счетчиков. не уверен, в чем может быть проблема. думал, что опубликую это как новый вопрос
@PeterCordes, попробовав что-то, обнаружил, что количество аппаратных счетчиков на моем ноутбуке равно 0. Есть ли у меня надежда использовать papi или это тупик?
@AnaKhorguani: Вы пробовали perf stat -d ./a.out, чтобы узнать, может ли он использовать какие-либо счетчики HW? Если это работает для циклов/инструкций/и т. д., возможно, вы неправильно используете библиотеку.
@PeterCordes Спасибо, ваш комментарий к другому сообщению помог. Теперь я могу больше тестировать с помощью papi и, надеюсь, смогу получить более точные результаты для промахов и попаданий в кэш процессора.
ваш код - единственное, что работает в вашей системе? прерывания и перестановки задач могут вызвать неожиданную разницу в часах