Затраты времени _mm_lfence() не являются детерминированными?
Я пытаюсь определить время, необходимое для чтения элемента, чтобы убедиться, что это попадание в кэш или его отсутствие. чтобы чтение было в порядке, я использую функцию _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.
2 ответа
Я получаю результаты более 1000 тактов за одну итерацию, а в следующий раз - 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, если это вошло в основной / исполняемый код ядра или нет.
Практический ответ: используйте rdtscp вместо rdtsc (наряду с барьером компилятора, я не уверен, что найденная вами версия будет иметь его) и отбросьте границы между вашими экземплярами rdtscp. Это не будет идеально, но это должно уменьшить ошибку. Вот немного устаревший пост, который должен быть полезен.
Больше, чем вы хотели знать: порядок заказов и спекуляции очень трудно рассуждать. Лфенс - очень тяжелый, сложный молоток. Это также уничтожает спекуляции после него, но само по себе может быть спекулятивно (забавно). Для более подробной информации проверьте этот пост.