Код бенчмаркинга — правильно ли я это делаю?

Я хочу сравнить C / C ++ код. Я хочу измерить время процессора, время стены и количество циклов / байт. Я написал несколько функций измерения, но у меня проблема с циклами / байтами.

Чтобы получить время процессора я написал функцию getrusage() с RUSAGE_SELFдля настенного времени я использую clock_gettime с MONOTONIC, чтобы получить циклы / байт я использую rdtsc,

Я обрабатываю входной буфер размером, например, 1024: char buffer[1024], Как мне проверить:

  1. Сделайте фазу разминки, просто позвоните fun2measure(args) 1000 раз:

for(int i=0; i<1000; i++)
fun2measure(args);

  1. Затем выполните тест в реальном времени для настенного времени:

    `без знака долго я;
    double timeTaken;
    double timeTotal = 3,0; // обрабатываем 3 секунды

    for (timeTaken = (double) 0, i = 0; timeTaken <= timeTotal; timeTaken = walltime (1), i ++)
    fun2measure (арг); `

  2. И за время процессора (почти то же самое):

    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]

Мои вопросы:

  1. Эти результаты в порядке?
  2. Почему, когда я увеличиваю время, я всегда получаю 0 циклов / байт в процессоре?
  3. Как я могу измерить среднее время, среднее значение, стандартное отклонение и т.д. статистику для такого бенчмаркинга?
  4. Мой метод бенчмаркинга на 100% в порядке?

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 больше не вопрос 🙂

3

Решение

Ваш эталонный счетчик циклов неверен, поскольку он включает в себя стоимость вызовов функций walltime / cputime. В общем, я настоятельно призываю вас использовать правильный профилировщик, а не пытаться изобретать велосипед. Особенно счетчики производительности дадут вам цифры, на которые вы можете положиться. Также обратите внимание, что циклы очень ненадежны, так как процессор обычно не работает с фиксированной частотой, или ядро ​​может переключать задачи и останавливать ваше приложение на некоторое время.

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

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]