Контрольный код — деление на количество итераций или нет?

У меня была интересная дискуссия с моим другом о тестировании кода C / C ++ (или кода в целом). Мы написали простую функцию, которая использует getrusage измерить время процессора для данного куска кода. (Он измеряет, сколько времени процессора потребовалось для запуска определенной функции). Позволь мне привести пример:

const int iterations = 409600;
double s = measureCPU();
for( j = 0; j < iterations; j++ )
function(args);
double e = measureCPU();
std::cout << (e-s)/iterations << " s \n";

Мы спорили, следует ли нам делить (e-s) на количество итераций или нет? Я имею в виду, что когда мы не делим его, результат находится в приемлемой форме (например, 3,0 с), но когда мы делим его, это дает нам результаты, такие как 2,34385e-07 с …

Итак, вот мои вопросы:

  1. мы должны разделить (e-s) на число итераций, если так, почему?
  2. Как мы можем напечатать 2.34385e-07 с в более удобочитаемой форме? (скажем, это заняло 0.00000003 с)?
  3. Должны ли мы сначала сделать вызов функции один раз, а после этого измерить время процессора для итераций, что-то вроде этого:

    // first function call, doesnt bother with it at all
    function(args);
    // real benchmarking
    const int iterations = 409600;
    double s = measureCPU();
    for( j = 0; j < iterations; j++ )
    function(args);
    double e = measureCPU();
    std::cout << (e-s)/iterations << " s \n";
    

3

Решение

  1. если вы разделите время на число итераций, то вы получите независимое от итераций сравнение времени выполнения одной функции: чем больше итераций, тем точнее результат. РЕДАКТИРОВАТЬ: его среднее время выполнения за n итераций.
  2. Вы можете умножить деленное время на 1e6, чтобы получить микросекунды за одну итерацию (я предполагаю, что measureCPU возвращает secods)

    std::cout << 1e6*(e-s)/iterations << " s \n";
    
  3. как заявлено @ ogni42, вы получаете накладные расходы из цикла for в измеренное время, поэтому вы можете попытаться развернуть цикл немного, чтобы уменьшить ошибку измерения, делать 8–16 вызовов на каждую итерацию, пробовать разные счетчики вызовов, чтобы увидеть, как измеренное время изменяется:

    for( j = 0; j < iterations; j++ ) {
    function(args);
    function(args);
    function(args);
    function(args);
    ...
    }
    
  4. То, что вы в основном получаете, это меньшее, лучшее число. Если бы вы хотели выше, то лучше забить, вы могли бы
    измерить различные варианты функции, а затем получить время самого быстрого. Этот мог набрать 10 очков.

    score_for_actual_function = 10.0 * fastest_time / time_of_actual_function
    

Эта оценка не зависит от времени, поэтому вы можете просто сравнить различные варианты функций, и функция может набрать менее одного балла … и остерегаться деления на ноль 🙂

3

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

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

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