Я хочу сравнить C / C ++ код. Я хочу измерить время процессора, время стены и количество циклов / байт. Я написал несколько функций измерения, но у меня проблема с циклами / байтами.
Чтобы получить время процессора я написал функцию getrusage()
с RUSAGE_SELF
для настенного времени я использую clock_gettime
с MONOTONIC
, чтобы получить циклы / байт я использую rdtsc
,
Я обрабатываю входной буфер размером, например, 1024: char buffer[1024]
, Как мне проверить:
fun2measure(args)
1000 раз:for(int i=0; i<1000; i++)
fun2measure(args);
Затем выполните тест в реальном времени для настенного времени:
`без знака долго я;
double timeTaken;
double timeTotal = 3,0; // обрабатываем 3 секунды
for (timeTaken = (double) 0, i = 0; timeTaken <= timeTotal; timeTaken = walltime (1), i ++)
fun2measure (арг); `
И за время процессора (почти то же самое):
for (timeTaken=(double)0, i=0; timeTaken <= timeTotal; timeTaken = walltime(1), i++)
fun2measure(args);
Но когда я хочу получить количество циклов процессора для функции, я использую этот кусок кода:
`unsigned long s = cyclecount();
for (timeTaken=(double)0, i=0; timeTaken <= timeTotal; timeTaken = walltime(1), i++)
{
fun2measure(args);
}
unsigned long e = cyclecount();
unsigned long s = cyclecount();
for (timeTaken=(double)0, i=0; timeTaken <= timeTotal; timeTaken = cputime(1), i++)
{
fun2measure(args);
}
unsigned long e = cyclecount();`
и затем посчитайте количество циклов / байт: ((e - s) / (i * inputsSize);
, Вот inputsSize
1024, потому что его длина buffer
, Но когда я встаю totalTime
до 10 с получаю странные результаты:
на 10 с:
Did fun2measure 1148531 times in 10.00 seconds for 1024 bytes, 0 cycles/byte [CPU]
Did fun2measure 1000221 times in 10.00 seconds for 1024 bytes, 3.000000 cycles/byte [WALL]
на 5 с:
Did fun2measure 578476 times in 5.00 seconds for 1024 bytes, 0 cycles/byte [CPU]
Did fun2measure 499542 times in 5.00 seconds for 1024 bytes, 7.000000 cycles/byte [WALL]
для 4с:
Did fun2measure 456828 times in 4.00 seconds for 1024 bytes, 4 cycles/byte [CPU]
Did fun2measure 396612 times in 4.00 seconds for 1024 bytes, 3.000000 cycles/byte [WALL]
Мои вопросы:
CHEERS!
1-е РЕДАКТИРОВАНИЕ:
После изменения i
в double
:
Did fun2measure 1138164.00 times in 10.00 seconds for 1024 bytes, 0.410739 cycles/byte [CPU]
Did fun2measure 999849.00 times in 10.00 seconds for 1024 bytes, 3.382036 cycles/byte [WALL]
мои результаты, кажется, в порядке. Так что вопрос №2 больше не вопрос 🙂
Ваш эталонный счетчик циклов неверен, поскольку он включает в себя стоимость вызовов функций walltime / cputime. В общем, я настоятельно призываю вас использовать правильный профилировщик, а не пытаться изобретать велосипед. Особенно счетчики производительности дадут вам цифры, на которые вы можете положиться. Также обратите внимание, что циклы очень ненадежны, так как процессор обычно не работает с фиксированной частотой, или ядро может переключать задачи и останавливать ваше приложение на некоторое время.
Я лично пишу тесты так, чтобы они выполняли данную функцию N раз, так как N достаточно велико, чтобы получить достаточно выборок. Внешне тогда я применяю такой профилировщик, как linux perf, чтобы заставить меня рассуждать. Повторяя эталонный тест в течение определенного времени, вы можете затем вычислить значения stddev / avg, что вы можете сделать в сценарии, который несколько раз запускает эталонный тест и оценивает выходные данные профилировщика.
Других решений пока нет …