Желательно ли использовать общее время, затрачиваемое на каноническую нагрузку, в качестве эталона или считать циклы / время, затрачиваемые отдельными операциями? - PullRequest
0 голосов
/ 15 октября 2018

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

Время выполнения каждой итерации рассматриваемой операциибыстр, возможно, 300-500 наносекунд.

1 Ответ

0 голосов
/ 15 октября 2018

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

Если вы считаете, что ваша среда выполнения может зависеть от данных и хотите изучить различия между итерациями, то вы можете каким-то образом рассмотреть возможность записи временных меток.Но 300 нс - это всего лишь ~ 1k тактов на 3,3 ГГц процессоре, а запись временной метки занимает некоторое время.Так что вам определенно нужно беспокоиться о затратах на измерения.


Если вы работаете на x86, необработанные rdtsc вокруг каждой операции довольно легковесны, но неупорядоченное выполнение может изменить порядок временных меток с помощьюРабота. Получить количество циклов ЦП? и clflush для аннулирования строки кэша с помощью функции C .

lfence; rdtsc; lfence, чтобы остановить изменение порядка синхронизации при каждой итерации рабочей нагрузки.заблокирует неупорядоченное выполнение шагов рабочей нагрузки, искажая вещи.(Окно выполнения не по порядку на Skylake имеет размер ROB, равный 224 моп. При 4 за такт это небольшая доля тактов в 1 Кбайт, но в коде с меньшей пропускной способностью и остановками для кеша может быть значительное перекрытие между независимымиитерации.)

Любые стандартные функции синхронизации, такие как C ++ std::chrono, обычно вызывают библиотечные функции, которые в конечном итоге используют rdtsc, но со многими дополнительными инструкциями.Или, что еще хуже, реальный системный вызов займёт более ста тактов для входа / выхода из ядра, и больше с включенным смягчением Meltdown + Spectre.


Однако одна вещь, которая может работать, - это использованиеIntel-PT (https://software.intel.com/en-us/blogs/2013/09/18/processor-tracing) для записи временных меток на взятых ветвях. Даже не блокируя exec-of-order exec, вы все равно можете получить временные метки при выполнении ветвления цикла в цикле повторения. Это вполне может быть независимо отваша рабочая нагрузка и возможность работать вскоре после ее выдачи в неработающей части ядра, но это может произойти только на ограниченном расстоянии до самой старой еще не вышедшей из употребления инструкции.

...