Затраты времени _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. Это не будет идеально, но это должно уменьшить ошибку. Вот немного устаревший пост, который должен быть полезен.

Больше, чем вы хотели знать: порядок заказов и спекуляции очень трудно рассуждать. Лфенс - очень тяжелый, сложный молоток. Это также уничтожает спекуляции после него, но само по себе может быть спекулятивно (забавно). Для более подробной информации проверьте этот пост.

Другие вопросы по тегам